@fitlab-ai/agent-infra 0.11.15 → 0.12.1
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 +19 -33
- package/dist/lib/internal/platform-comment.js +59 -9
- package/dist/lib/internal/task-activity.js +1 -12
- package/dist/lib/internal/task-event.js +1 -12
- 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/issue-comments.js +373 -267
- package/dist/lib/platform/issue-summary-content.js +112 -0
- package/dist/lib/platform/pr-change-report.js +175 -26
- package/dist/lib/platform/pr-summary-content.js +54 -0
- package/dist/lib/platform/pr-summary.js +321 -296
- package/dist/lib/platform/pull-requests.js +3 -15
- package/dist/lib/platform/summary-content-pipeline.js +18 -0
- package/dist/lib/pr-review/evidence-grading.js +3 -2
- package/dist/lib/process-data/index.js +5 -4
- 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/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 +62 -12
- package/dist/lib/sandbox/task-resolver.js +9 -6
- package/dist/lib/sandbox/workspace-identity.js +6 -5
- 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 +33 -29
- package/dist/lib/task/lifecycle.js +9 -48
- 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 +87 -88
- 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 +10 -8
- 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 +20 -37
- package/lib/internal/platform-comment.ts +49 -6
- package/lib/internal/task-activity.ts +1 -10
- package/lib/internal/task-event.ts +1 -10
- 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/issue-comments.ts +478 -280
- package/lib/platform/issue-summary-content.ts +132 -0
- package/lib/platform/pr-change-report.ts +165 -20
- package/lib/platform/pr-summary-content.ts +60 -0
- package/lib/platform/pr-summary.ts +367 -269
- package/lib/platform/pull-requests.ts +3 -24
- package/lib/platform/summary-content-pipeline.ts +23 -0
- package/lib/pr-review/evidence-grading.ts +3 -2
- package/lib/process-data/index.ts +4 -3
- 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/task-view.ts +4 -2
- package/lib/sandbox/mounts.ts +4 -4
- package/lib/sandbox/recovery.ts +26 -18
- package/lib/sandbox/removal.ts +60 -27
- package/lib/sandbox/task-resolver.ts +9 -6
- package/lib/sandbox/workspace-identity.ts +6 -5
- 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 +27 -30
- package/lib/task/lifecycle.ts +9 -50
- package/lib/task/local-artifact-finalization.ts +1 -4
- package/lib/task/orchestration.ts +31 -80
- package/lib/task/platform-operation-recovery.ts +70 -82
- 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 +10 -8
- 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 +5 -3
- package/templates/.agents/rules/pr-sync.zh-CN.md +7 -10
- 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 +7 -7
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +7 -7
- 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 +2 -2
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +2 -2
- 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 +3 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-task/SKILL.en.md +15 -30
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +17 -32
- 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 +10 -3
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +10 -3
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +3 -3
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +3 -3
- 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 -22
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +4 -22
- 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/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-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 +4 -4
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/watch-pr/config/verify.json +0 -1
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +3 -3
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +3 -3
- 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/task/task-execution-lock.js +0 -250
- package/lib/task/task-execution-lock.ts +0 -320
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,15 +9,15 @@ 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';
|
|
19
18
|
import { readSandboxControlManifest } from '../sandbox/control/lifecycle.js';
|
|
20
19
|
import { validateSandboxControlIdentity } from '../sandbox/control/identity-sentinel.js';
|
|
20
|
+
import { parseDeliverySummaryContent, renderDeliverySummaryContent } from '../platform/issue-summary-content.js';
|
|
21
21
|
const RECEIPT_VERSION = 4;
|
|
22
22
|
const FINALIZATION_STEPS = ['lifecycle', 'task-comment', 'verification', 'summary'];
|
|
23
23
|
export function resolveTaskFinalizationDirectory(repoRoot, taskId) {
|
|
@@ -442,7 +442,7 @@ function mutationPatch(current, mutation) {
|
|
|
442
442
|
? { warningProjection: 'done', lastError: null }
|
|
443
443
|
: { warningProjection: 'pending', lastError: mutation.error };
|
|
444
444
|
}
|
|
445
|
-
function
|
|
445
|
+
function mutateFinalizationReceipt(repoRoot, receipt, capability, mutation, consumed) {
|
|
446
446
|
if (!hasFinalizationTaskDocument(repoRoot, receipt.taskId)) {
|
|
447
447
|
throw capabilityError('FINALIZATION_SCOPE_INVALID', 'finalization capability requires an active task or a completed task');
|
|
448
448
|
}
|
|
@@ -459,7 +459,7 @@ function applyFinalizationReceiptMutation(repoRoot, receipt, capability, mutatio
|
|
|
459
459
|
if (!hasFinalizationTaskDocument(repoRoot, receipt.taskId)) {
|
|
460
460
|
throw capabilityError('FINALIZATION_SCOPE_INVALID', 'finalization capability requires an active task or a completed task');
|
|
461
461
|
}
|
|
462
|
-
return
|
|
462
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, mutation, new Set());
|
|
463
463
|
}
|
|
464
464
|
function warningKey(warning) {
|
|
465
465
|
return `${warning.step}\0${warning.code}\0${warning.target}`;
|
|
@@ -479,14 +479,14 @@ function reconcileWarningProjection(repoRoot, taskId, receipt, consumed) {
|
|
|
479
479
|
retryable: true
|
|
480
480
|
};
|
|
481
481
|
const capability = issueCapability(receipt, 'warning-projection');
|
|
482
|
-
return
|
|
482
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
catch (error) {
|
|
486
486
|
const detail = errorOf(error, 'FINALIZATION_WARNING_PROJECTION_FAILED', true);
|
|
487
487
|
try {
|
|
488
488
|
const capability = issueCapability(receipt, 'warning-projection');
|
|
489
|
-
return
|
|
489
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
|
|
490
490
|
}
|
|
491
491
|
catch {
|
|
492
492
|
return receipt;
|
|
@@ -495,7 +495,7 @@ function reconcileWarningProjection(repoRoot, taskId, receipt, consumed) {
|
|
|
495
495
|
}
|
|
496
496
|
try {
|
|
497
497
|
const capability = issueCapability(receipt, 'warning-projection');
|
|
498
|
-
return
|
|
498
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'succeeded' }, consumed);
|
|
499
499
|
}
|
|
500
500
|
catch {
|
|
501
501
|
return receipt;
|
|
@@ -526,7 +526,7 @@ async function syncPendingTaskComment(input) {
|
|
|
526
526
|
if (result.status === 'applied' || result.status === 'no-op') {
|
|
527
527
|
const skipped = result.error?.code === 'ISSUE_NOT_LINKED';
|
|
528
528
|
const capability = issueCapability(receipt, 'task-comment');
|
|
529
|
-
receipt =
|
|
529
|
+
receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
|
|
530
530
|
scope: 'task-comment', operation: 'succeeded', state: skipped ? 'skipped' : 'done'
|
|
531
531
|
}, consumedCapabilities);
|
|
532
532
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
@@ -542,7 +542,7 @@ async function syncPendingTaskComment(input) {
|
|
|
542
542
|
}
|
|
543
543
|
const detail = step.error ?? { code: 'COMMENT_SYNC_FAILED', message: 'task comment synchronization failed', retryable: true };
|
|
544
544
|
const capability = issueCapability(receipt, 'task-comment');
|
|
545
|
-
receipt =
|
|
545
|
+
receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
|
|
546
546
|
scope: 'task-comment', operation: 'failed', error: detail
|
|
547
547
|
}, consumedCapabilities);
|
|
548
548
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
@@ -552,7 +552,7 @@ async function syncPendingTaskComment(input) {
|
|
|
552
552
|
const detail = errorOf(error, 'COMMENT_SYNC_FAILED', true);
|
|
553
553
|
try {
|
|
554
554
|
const capability = issueCapability(receipt, 'task-comment');
|
|
555
|
-
receipt =
|
|
555
|
+
receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
|
|
556
556
|
scope: 'task-comment', operation: 'failed', error: detail
|
|
557
557
|
}, consumedCapabilities);
|
|
558
558
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
@@ -570,17 +570,25 @@ function readDeliverySummary(taskDir, taskId) {
|
|
|
570
570
|
catch {
|
|
571
571
|
throw Object.assign(new Error('delivery summary staging record is unavailable'), { code: 'SUMMARY_STAGING_INVALID' });
|
|
572
572
|
}
|
|
573
|
-
if (value.taskId !== taskId ||
|
|
573
|
+
if (value.taskId !== taskId || !value.content || typeof value.contentSha256 !== 'string') {
|
|
574
574
|
throw Object.assign(new Error('delivery summary staging record is invalid'), { code: 'SUMMARY_STAGING_INVALID' });
|
|
575
575
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
576
|
+
let content;
|
|
577
|
+
try {
|
|
578
|
+
content = parseDeliverySummaryContent(value.content);
|
|
579
|
+
}
|
|
580
|
+
catch {
|
|
581
|
+
throw Object.assign(new Error('delivery summary staging payload is invalid'), { code: 'SUMMARY_STAGING_INVALID' });
|
|
579
582
|
}
|
|
583
|
+
if (content.taskId !== taskId || createHash('sha256').update(JSON.stringify(content)).digest('hex') !== value.contentSha256) {
|
|
584
|
+
throw Object.assign(new Error('delivery summary staging digest does not match payload'), { code: 'SUMMARY_STAGING_INVALID' });
|
|
585
|
+
}
|
|
586
|
+
const body = renderDeliverySummaryContent(content);
|
|
587
|
+
const canonical = canonicalizeSummaryBody(body);
|
|
588
|
+
if (!canonical.ok)
|
|
589
|
+
throw Object.assign(new Error('delivery summary staging body is not canonical'), { code: 'SUMMARY_STAGING_INVALID' });
|
|
580
590
|
const digest = createHash('sha256').update(canonical.value).digest('hex');
|
|
581
|
-
|
|
582
|
-
throw Object.assign(new Error('delivery summary staging digest does not match body'), { code: 'SUMMARY_STAGING_INVALID' });
|
|
583
|
-
return { body: canonical.value, sha256: value.sha256 };
|
|
591
|
+
return { body: canonical.value, sha256: digest };
|
|
584
592
|
}
|
|
585
593
|
async function syncPendingSummary(input) {
|
|
586
594
|
let { receipt } = input;
|
|
@@ -682,9 +690,9 @@ function preparedResult(taskId, receipt, steps, changed) {
|
|
|
682
690
|
result: 'prepared', warnings: openWarnings(receipt), error: null
|
|
683
691
|
};
|
|
684
692
|
}
|
|
685
|
-
async function
|
|
693
|
+
async function prepareTaskFinalizationCore(request, taskId, options) {
|
|
686
694
|
const repoRoot = path.resolve(options.repoRoot);
|
|
687
|
-
const lifecycle = options.lifecycle ?? ((lifecycleRequest, lifecycleOptions) => (
|
|
695
|
+
const lifecycle = options.lifecycle ?? ((lifecycleRequest, lifecycleOptions) => (applyTaskLifecycle(lifecycleRequest, lifecycleOptions ?? { repoRoot })));
|
|
688
696
|
const backfill = options.backfill ?? backfillCompletionComments;
|
|
689
697
|
const commentSync = options.commentSync ?? syncPlatformComment;
|
|
690
698
|
const issueSync = options.issueSync ?? syncPlatformIssue;
|
|
@@ -966,12 +974,10 @@ async function prepareTaskFinalization(request, options) {
|
|
|
966
974
|
if (!resolved.ok)
|
|
967
975
|
return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
|
|
968
976
|
try {
|
|
969
|
-
return await
|
|
977
|
+
return await prepareTaskFinalizationCore(request, resolved.taskId, options);
|
|
970
978
|
}
|
|
971
979
|
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');
|
|
980
|
+
const detail = errorOf(error, 'TASK_FINALIZATION_FAILED');
|
|
975
981
|
return failed(resolved.taskId, detail);
|
|
976
982
|
}
|
|
977
983
|
}
|
|
@@ -984,7 +990,7 @@ async function commitPreparedTaskFinalization(request, options) {
|
|
|
984
990
|
if (!resolved.ok)
|
|
985
991
|
return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
|
|
986
992
|
try {
|
|
987
|
-
return await
|
|
993
|
+
return await (async () => {
|
|
988
994
|
if (options.controlBinding && options.manifestPath) {
|
|
989
995
|
try {
|
|
990
996
|
const manifest = readSandboxControlManifest(options.manifestPath);
|
|
@@ -1051,7 +1057,7 @@ async function commitPreparedTaskFinalization(request, options) {
|
|
|
1051
1057
|
};
|
|
1052
1058
|
const result = options.lifecycle
|
|
1053
1059
|
? options.lifecycle(lifecycleRequest, lifecycleOptions)
|
|
1054
|
-
:
|
|
1060
|
+
: applyTaskLifecycle(lifecycleRequest, lifecycleOptions);
|
|
1055
1061
|
const step = lifecycleStep(result);
|
|
1056
1062
|
if (result.status !== 'applied' && result.status !== 'no-op') {
|
|
1057
1063
|
const updated = updateReceipt(repoRoot, receipt, { lifecycle: 'pending', lastError: step.error });
|
|
@@ -1131,12 +1137,10 @@ async function commitPreparedTaskFinalization(request, options) {
|
|
|
1131
1137
|
});
|
|
1132
1138
|
}
|
|
1133
1139
|
return terminalResult(resolved.taskId, updated, { lifecycle: step, verification }, result.changed, detail);
|
|
1134
|
-
});
|
|
1140
|
+
})();
|
|
1135
1141
|
}
|
|
1136
1142
|
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');
|
|
1143
|
+
const detail = errorOf(error, 'TASK_FINALIZATION_FAILED');
|
|
1140
1144
|
return failed(resolved.taskId, detail);
|
|
1141
1145
|
}
|
|
1142
1146
|
}
|
|
@@ -13,7 +13,7 @@ import { validateCurrentTaskContract } from './current-contract.js';
|
|
|
13
13
|
import { isValidAgentInfraVersion } from '../version.js';
|
|
14
14
|
import { taskIssueIdentity } from '../platform/task-identities.js';
|
|
15
15
|
import { resourceIdentityEquals } from '../platform/resource-identity.js';
|
|
16
|
-
import {
|
|
16
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.js';
|
|
17
17
|
const lifecycleIntentCatalog = [
|
|
18
18
|
'block', 'activate', 'cancel', 'complete', 'close-codescan', 'close-dependabot', 'restore', 'recover-started'
|
|
19
19
|
];
|
|
@@ -61,7 +61,7 @@ const DEFAULT_IO = {
|
|
|
61
61
|
};
|
|
62
62
|
function isVirtiofsMountPoint(directory, mountInfo) {
|
|
63
63
|
const decodeMountInfoPath = (value) => value.replace(/\\([0-7]{3})/gu, (_match, octal) => String.fromCharCode(Number.parseInt(octal, 8)));
|
|
64
|
-
const expected =
|
|
64
|
+
const expected = fs.realpathSync.native(directory);
|
|
65
65
|
return mountInfo.split('\n').some((line) => {
|
|
66
66
|
if (!line)
|
|
67
67
|
return false;
|
|
@@ -371,7 +371,7 @@ function validateRestoreStaging(request, repoRoot, taskId) {
|
|
|
371
371
|
let workspace;
|
|
372
372
|
let stagingDir;
|
|
373
373
|
try {
|
|
374
|
-
workspace = fs.realpathSync.native(
|
|
374
|
+
workspace = fs.realpathSync.native(resolveProjectTaskWorkspaceRoot(repoRoot));
|
|
375
375
|
stagingDir = fs.realpathSync.native(path.resolve(request.stagingDir));
|
|
376
376
|
}
|
|
377
377
|
catch (error) {
|
|
@@ -379,7 +379,7 @@ function validateRestoreStaging(request, repoRoot, taskId) {
|
|
|
379
379
|
}
|
|
380
380
|
const relative = path.relative(workspace, stagingDir);
|
|
381
381
|
if (!relative || relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative) || path.basename(stagingDir) === taskId) {
|
|
382
|
-
return { code: 'LIFECYCLE_STAGING_INVALID', message: 'restore staging must be a non-final directory inside
|
|
382
|
+
return { code: 'LIFECYCLE_STAGING_INVALID', message: 'restore staging must be a non-final directory inside the project task workspace' };
|
|
383
383
|
}
|
|
384
384
|
let entries;
|
|
385
385
|
try {
|
|
@@ -594,7 +594,7 @@ export function inspectTaskLifecycleProgress(repoRoot, taskId, agent) {
|
|
|
594
594
|
return 'unknown';
|
|
595
595
|
}
|
|
596
596
|
}
|
|
597
|
-
function
|
|
597
|
+
function applyTaskLifecycle(requestInput, options = {}) {
|
|
598
598
|
if (requestInput.intent === 'recover-started') {
|
|
599
599
|
return failed(requestInput, { code: 'LIFECYCLE_RECOVERY_REQUIRES_AUTHORITY', message: 'recover-started must be dispatched through task control authority' });
|
|
600
600
|
}
|
|
@@ -649,7 +649,7 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
649
649
|
else {
|
|
650
650
|
return failed(request, { code: 'LIFECYCLE_TASK_NOT_FOUND', message: `task ${taskId} has no lifecycle source` }, { taskId });
|
|
651
651
|
}
|
|
652
|
-
const targetPath = path.join(repoRoot,
|
|
652
|
+
const targetPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), spec.target, taskId);
|
|
653
653
|
const requiredSteps = stepsForIntent(request.intent);
|
|
654
654
|
const movingTaskDirectory = sourcePath !== targetPath;
|
|
655
655
|
const currentTaskFile = path.join(sourcePath, 'task.md');
|
|
@@ -695,7 +695,7 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
695
695
|
return failed(request, { code: 'LIFECYCLE_DOCUMENT_INVALID', message: contract.message }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
696
696
|
}
|
|
697
697
|
const registryRequest = executeShortIdCommand({
|
|
698
|
-
operation: 'list', activeDir: path.join(repoRoot, '
|
|
698
|
+
operation: 'list', activeDir: path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active'),
|
|
699
699
|
shortIdLength: configuredShortIdLength(repoRoot)
|
|
700
700
|
});
|
|
701
701
|
if (registryRequest.status === 'failed') {
|
|
@@ -905,7 +905,7 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
905
905
|
}
|
|
906
906
|
}
|
|
907
907
|
}
|
|
908
|
-
const activeTaskPath = path.join(repoRoot, '
|
|
908
|
+
const activeTaskPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', taskId);
|
|
909
909
|
if (request.intent === 'complete' && fs.existsSync(activeTaskPath)) {
|
|
910
910
|
try {
|
|
911
911
|
let sourceIsVirtiofsMount = false;
|
|
@@ -967,44 +967,5 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
967
967
|
journalPath, completedSteps: [...completed], pendingSteps: []
|
|
968
968
|
};
|
|
969
969
|
}
|
|
970
|
-
|
|
971
|
-
const normalized = normalizedRequest(request);
|
|
972
|
-
if ('code' in normalized)
|
|
973
|
-
return applyTaskLifecycleUnlocked(request, options);
|
|
974
|
-
const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
|
|
975
|
-
const taskId = normalized.intent === 'restore'
|
|
976
|
-
? normalized.taskRef
|
|
977
|
-
: (() => {
|
|
978
|
-
const resolved = resolveTaskRef(normalized.taskRef, { repoRoot });
|
|
979
|
-
return resolved.ok ? resolved.taskId : null;
|
|
980
|
-
})();
|
|
981
|
-
if (!taskId)
|
|
982
|
-
return applyTaskLifecycleUnlocked(request, options);
|
|
983
|
-
try {
|
|
984
|
-
return withTaskExecutionLock(repoRoot, taskId, 'task-lifecycle.move', () => applyTaskLifecycleUnlocked(request, options));
|
|
985
|
-
}
|
|
986
|
-
catch (error) {
|
|
987
|
-
if (error instanceof TaskExecutionLockError) {
|
|
988
|
-
return failed(request, { code: error.code, message: error.message }, { taskId });
|
|
989
|
-
}
|
|
990
|
-
throw error;
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
function applyTaskLifecycleWithinTaskLock(request, options, lockedTaskId) {
|
|
994
|
-
const normalized = normalizedRequest(request);
|
|
995
|
-
if ('code' in normalized)
|
|
996
|
-
return failed(request, normalized);
|
|
997
|
-
const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
|
|
998
|
-
const resolved = normalized.intent === 'restore'
|
|
999
|
-
? { ok: true, taskId: normalized.taskRef }
|
|
1000
|
-
: resolveTaskRef(normalized.taskRef, { repoRoot });
|
|
1001
|
-
if (!resolved.ok || resolved.taskId !== lockedTaskId) {
|
|
1002
|
-
return failed(request, {
|
|
1003
|
-
code: 'LIFECYCLE_LOCK_SCOPE_MISMATCH',
|
|
1004
|
-
message: 'task lifecycle request does not match the held task lock'
|
|
1005
|
-
}, { taskId: resolved.ok ? resolved.taskId : resolved.taskId });
|
|
1006
|
-
}
|
|
1007
|
-
return applyTaskLifecycleUnlocked(request, options);
|
|
1008
|
-
}
|
|
1009
|
-
export { lifecycleIntentCatalog, lifecycleFailureCatalog, lifecycleProducerCatalog, applyTaskLifecycle, applyTaskLifecycleWithinTaskLock, previewTaskCompletion };
|
|
970
|
+
export { lifecycleIntentCatalog, lifecycleFailureCatalog, lifecycleProducerCatalog, applyTaskLifecycle, previewTaskCompletion };
|
|
1010
971
|
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -110,8 +110,7 @@ function prepareLocalArtifact(request, candidate) {
|
|
|
110
110
|
return {
|
|
111
111
|
result: validation.ok && !qualificationError ? { ...result, status: 'passed', error: null } : result,
|
|
112
112
|
content,
|
|
113
|
-
repoRoot: resolved.repoRoot
|
|
114
|
-
lockAlreadyHeld: request.lockAlreadyHeld
|
|
113
|
+
repoRoot: resolved.repoRoot
|
|
115
114
|
};
|
|
116
115
|
}
|
|
117
116
|
function commitLocalArtifactProvenance(prepared) {
|