@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
|
@@ -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
|
];
|
|
@@ -54,8 +54,24 @@ const DEFAULT_IO = {
|
|
|
54
54
|
renameSync: (source, target) => fs.renameSync(source, target),
|
|
55
55
|
readFileSync: (file) => fs.readFileSync(file, 'utf8'),
|
|
56
56
|
writeFileSync: (file, content, flag) => fs.writeFileSync(file, content, { encoding: 'utf8', flag: flag ?? 'w' }),
|
|
57
|
-
unlinkSync: (file) => fs.unlinkSync(file)
|
|
57
|
+
unlinkSync: (file) => fs.unlinkSync(file),
|
|
58
|
+
rmdirSync: (directory) => fs.rmdirSync(directory),
|
|
59
|
+
readdirSync: (directory) => fs.readdirSync(directory),
|
|
60
|
+
readMountInfoSync: () => fs.readFileSync('/proc/self/mountinfo', 'utf8')
|
|
58
61
|
};
|
|
62
|
+
function isVirtiofsMountPoint(directory, mountInfo) {
|
|
63
|
+
const decodeMountInfoPath = (value) => value.replace(/\\([0-7]{3})/gu, (_match, octal) => String.fromCharCode(Number.parseInt(octal, 8)));
|
|
64
|
+
const expected = fs.realpathSync.native(directory);
|
|
65
|
+
return mountInfo.split('\n').some((line) => {
|
|
66
|
+
if (!line)
|
|
67
|
+
return false;
|
|
68
|
+
const fields = line.split(' ');
|
|
69
|
+
const separator = fields.indexOf('-');
|
|
70
|
+
return separator >= 0
|
|
71
|
+
&& fields[separator + 1] === 'virtiofs'
|
|
72
|
+
&& path.resolve(decodeMountInfoPath(fields[4] ?? '')) === expected;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
59
75
|
function failed(request, error, extra = {}) {
|
|
60
76
|
return {
|
|
61
77
|
status: 'failed', changed: false, requestRef: request.taskRef, taskId: null,
|
|
@@ -355,7 +371,7 @@ function validateRestoreStaging(request, repoRoot, taskId) {
|
|
|
355
371
|
let workspace;
|
|
356
372
|
let stagingDir;
|
|
357
373
|
try {
|
|
358
|
-
workspace = fs.realpathSync.native(
|
|
374
|
+
workspace = fs.realpathSync.native(resolveProjectTaskWorkspaceRoot(repoRoot));
|
|
359
375
|
stagingDir = fs.realpathSync.native(path.resolve(request.stagingDir));
|
|
360
376
|
}
|
|
361
377
|
catch (error) {
|
|
@@ -363,7 +379,7 @@ function validateRestoreStaging(request, repoRoot, taskId) {
|
|
|
363
379
|
}
|
|
364
380
|
const relative = path.relative(workspace, stagingDir);
|
|
365
381
|
if (!relative || relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative) || path.basename(stagingDir) === taskId) {
|
|
366
|
-
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' };
|
|
367
383
|
}
|
|
368
384
|
let entries;
|
|
369
385
|
try {
|
|
@@ -578,7 +594,7 @@ export function inspectTaskLifecycleProgress(repoRoot, taskId, agent) {
|
|
|
578
594
|
return 'unknown';
|
|
579
595
|
}
|
|
580
596
|
}
|
|
581
|
-
function
|
|
597
|
+
function applyTaskLifecycle(requestInput, options = {}) {
|
|
582
598
|
if (requestInput.intent === 'recover-started') {
|
|
583
599
|
return failed(requestInput, { code: 'LIFECYCLE_RECOVERY_REQUIRES_AUTHORITY', message: 'recover-started must be dispatched through task control authority' });
|
|
584
600
|
}
|
|
@@ -633,7 +649,7 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
633
649
|
else {
|
|
634
650
|
return failed(request, { code: 'LIFECYCLE_TASK_NOT_FOUND', message: `task ${taskId} has no lifecycle source` }, { taskId });
|
|
635
651
|
}
|
|
636
|
-
const targetPath = path.join(repoRoot,
|
|
652
|
+
const targetPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), spec.target, taskId);
|
|
637
653
|
const requiredSteps = stepsForIntent(request.intent);
|
|
638
654
|
const movingTaskDirectory = sourcePath !== targetPath;
|
|
639
655
|
const currentTaskFile = path.join(sourcePath, 'task.md');
|
|
@@ -679,7 +695,7 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
679
695
|
return failed(request, { code: 'LIFECYCLE_DOCUMENT_INVALID', message: contract.message }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
680
696
|
}
|
|
681
697
|
const registryRequest = executeShortIdCommand({
|
|
682
|
-
operation: 'list', activeDir: path.join(repoRoot, '
|
|
698
|
+
operation: 'list', activeDir: path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active'),
|
|
683
699
|
shortIdLength: configuredShortIdLength(repoRoot)
|
|
684
700
|
});
|
|
685
701
|
if (registryRequest.status === 'failed') {
|
|
@@ -889,10 +905,22 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
889
905
|
}
|
|
890
906
|
}
|
|
891
907
|
}
|
|
892
|
-
const activeTaskPath = path.join(repoRoot, '
|
|
908
|
+
const activeTaskPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', taskId);
|
|
893
909
|
if (request.intent === 'complete' && fs.existsSync(activeTaskPath)) {
|
|
894
910
|
try {
|
|
895
|
-
|
|
911
|
+
let sourceIsVirtiofsMount = false;
|
|
912
|
+
try {
|
|
913
|
+
sourceIsVirtiofsMount = isVirtiofsMountPoint(activeTaskPath, io.readMountInfoSync());
|
|
914
|
+
}
|
|
915
|
+
catch { /* Platforms without mountinfo retain the ordinary directory cleanup path. */ }
|
|
916
|
+
if (sourceIsVirtiofsMount) {
|
|
917
|
+
if (io.readdirSync(activeTaskPath).length > 0) {
|
|
918
|
+
throw new Error('virtiofs source directory is not empty after task contents were transferred');
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
io.rmdirSync(activeTaskPath);
|
|
923
|
+
}
|
|
896
924
|
}
|
|
897
925
|
catch (error) {
|
|
898
926
|
return failed(request, { code: 'LIFECYCLE_SOURCE_DIRECTORY_CLEANUP_FAILED', message: String(error) }, {
|
|
@@ -939,44 +967,5 @@ function applyTaskLifecycleUnlocked(requestInput, options = {}) {
|
|
|
939
967
|
journalPath, completedSteps: [...completed], pendingSteps: []
|
|
940
968
|
};
|
|
941
969
|
}
|
|
942
|
-
|
|
943
|
-
const normalized = normalizedRequest(request);
|
|
944
|
-
if ('code' in normalized)
|
|
945
|
-
return applyTaskLifecycleUnlocked(request, options);
|
|
946
|
-
const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
|
|
947
|
-
const taskId = normalized.intent === 'restore'
|
|
948
|
-
? normalized.taskRef
|
|
949
|
-
: (() => {
|
|
950
|
-
const resolved = resolveTaskRef(normalized.taskRef, { repoRoot });
|
|
951
|
-
return resolved.ok ? resolved.taskId : null;
|
|
952
|
-
})();
|
|
953
|
-
if (!taskId)
|
|
954
|
-
return applyTaskLifecycleUnlocked(request, options);
|
|
955
|
-
try {
|
|
956
|
-
return withTaskExecutionLock(repoRoot, taskId, 'task-lifecycle.move', () => applyTaskLifecycleUnlocked(request, options));
|
|
957
|
-
}
|
|
958
|
-
catch (error) {
|
|
959
|
-
if (error instanceof TaskExecutionLockError) {
|
|
960
|
-
return failed(request, { code: error.code, message: error.message }, { taskId });
|
|
961
|
-
}
|
|
962
|
-
throw error;
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
function applyTaskLifecycleWithinTaskLock(request, options, lockedTaskId) {
|
|
966
|
-
const normalized = normalizedRequest(request);
|
|
967
|
-
if ('code' in normalized)
|
|
968
|
-
return failed(request, normalized);
|
|
969
|
-
const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
|
|
970
|
-
const resolved = normalized.intent === 'restore'
|
|
971
|
-
? { ok: true, taskId: normalized.taskRef }
|
|
972
|
-
: resolveTaskRef(normalized.taskRef, { repoRoot });
|
|
973
|
-
if (!resolved.ok || resolved.taskId !== lockedTaskId) {
|
|
974
|
-
return failed(request, {
|
|
975
|
-
code: 'LIFECYCLE_LOCK_SCOPE_MISMATCH',
|
|
976
|
-
message: 'task lifecycle request does not match the held task lock'
|
|
977
|
-
}, { taskId: resolved.ok ? resolved.taskId : resolved.taskId });
|
|
978
|
-
}
|
|
979
|
-
return applyTaskLifecycleUnlocked(request, options);
|
|
980
|
-
}
|
|
981
|
-
export { lifecycleIntentCatalog, lifecycleFailureCatalog, lifecycleProducerCatalog, applyTaskLifecycle, applyTaskLifecycleWithinTaskLock, previewTaskCompletion };
|
|
970
|
+
export { lifecycleIntentCatalog, lifecycleFailureCatalog, lifecycleProducerCatalog, applyTaskLifecycle, previewTaskCompletion };
|
|
982
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) {
|
|
@@ -7,19 +7,19 @@ import { validateCurrentTaskContract } from './current-contract.js';
|
|
|
7
7
|
import { parseReviewSummary } from './review-artifacts.js';
|
|
8
8
|
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.js';
|
|
9
9
|
import { resolveTaskRef, TASK_ID_RE } from './resolve-ref.js';
|
|
10
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.js';
|
|
10
11
|
import { activateDelegation, abortActivatedDelegation, abortPreparedDelegation, completeDelegationStage, consumeDelegation, dispatchDelegation, foldBlankToNull, isDelegationReceipt, managedDelegationRole, prepareDelegation, sealDelegation } from './delegation-receipts.js';
|
|
11
12
|
import { normalizeAgentClients } from '../agent-clients/config.js';
|
|
12
13
|
import { getAgentClientAdapter, getAgentClientCapability, getAgentClientDelegationEvidence, getAgentClientModelSelection } from '../agent-clients/registry.js';
|
|
13
14
|
import { isAgentClientId } from '../agent-clients/types.js';
|
|
14
15
|
import { captureRepositorySnapshot, captureWorkspaceSnapshot, diffWorkspaceSnapshots } from './workspace-snapshot.js';
|
|
15
16
|
import { assertGitRepositoryBinding } from '../git/worktree-identity.js';
|
|
16
|
-
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
|
|
17
17
|
import { extractReviewBaseline, extractReviewDiffBase, extractReviewTargetHead, extractReviewedHead } from './review-fingerprint.js';
|
|
18
18
|
import { resolveDeliveryTarget, resolveDiffBase, resolveTargetHead } from './delivery-target.js';
|
|
19
19
|
import { buildLifecycleFacts, canStart, recommendNext } from './capabilities.js';
|
|
20
20
|
import { hasOpenLifecycleExecution } from './activity-log.js';
|
|
21
21
|
import { normalizeAgentToken } from '../agent-clients/tokens.js';
|
|
22
|
-
import {
|
|
22
|
+
import { resolveArtifactContextForResolvedTask } from './artifact-lifecycle.js';
|
|
23
23
|
function supportsLifecycleDelegation(client) {
|
|
24
24
|
return getAgentClientCapability(client, 'subagents').level !== 'unsupported'
|
|
25
25
|
&& getAgentClientCapability(client, 'orchestration').level !== 'unsupported'
|
|
@@ -274,15 +274,9 @@ function mutateDelegationAdapterEvidence(taskRef, receiptId, adapterId, mutate,
|
|
|
274
274
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
275
275
|
if (!resolved.ok)
|
|
276
276
|
throw new Error(`${resolved.code}: ${resolved.message}`);
|
|
277
|
-
return mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options
|
|
277
|
+
return mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options);
|
|
278
278
|
}
|
|
279
|
-
function
|
|
280
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
281
|
-
if (!resolved.ok)
|
|
282
|
-
throw new Error(`${resolved.code}: ${resolved.message}`);
|
|
283
|
-
return mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options, true);
|
|
284
|
-
}
|
|
285
|
-
function mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options, taskLockHeld) {
|
|
279
|
+
function mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options) {
|
|
286
280
|
const update = () => {
|
|
287
281
|
try {
|
|
288
282
|
const run = readRun(resolved.taskDir, options);
|
|
@@ -316,9 +310,7 @@ function mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterI
|
|
|
316
310
|
}
|
|
317
311
|
};
|
|
318
312
|
let mutationError;
|
|
319
|
-
const result =
|
|
320
|
-
? update()
|
|
321
|
-
: withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `agent-adapter.${adapterId}.evidence`, update);
|
|
313
|
+
const result = update();
|
|
322
314
|
if (mutationError)
|
|
323
315
|
throw mutationError;
|
|
324
316
|
return result;
|
|
@@ -542,10 +534,7 @@ function routeFromFacts(facts) {
|
|
|
542
534
|
const role = action.startsWith('review-') ? 'reviewer' : 'executor';
|
|
543
535
|
return { action: command, role, stage: action };
|
|
544
536
|
}
|
|
545
|
-
function
|
|
546
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
547
|
-
if (!resolved.ok)
|
|
548
|
-
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
537
|
+
function routeResolvedTask(taskRef, resolved, options) {
|
|
549
538
|
let gitRoot;
|
|
550
539
|
try {
|
|
551
540
|
gitRoot = gitRootFor(resolved.repoRoot, options);
|
|
@@ -584,7 +573,7 @@ function routeOrchestration(taskRef, options = {}) {
|
|
|
584
573
|
catch (error) {
|
|
585
574
|
return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
586
575
|
}
|
|
587
|
-
const facts = buildLifecycleFacts(resolved.taskDir, content, resolved.state, hasOpenLifecycleExecution(content) || Boolean(run?.pendingDelegation));
|
|
576
|
+
const facts = buildLifecycleFacts(resolved.taskDir, content, resolved.state, hasOpenLifecycleExecution(content) || Boolean(run?.pendingDelegation), resolved.repoRoot);
|
|
588
577
|
if (!facts.ok)
|
|
589
578
|
return failed('ORCHESTRATION_CAPABILITY_FACTS_INVALID', facts.message, resolved.taskId);
|
|
590
579
|
const routed = routeFromFacts(facts.facts);
|
|
@@ -674,7 +663,7 @@ function routeOrchestration(taskRef, options = {}) {
|
|
|
674
663
|
}
|
|
675
664
|
const action = routed.stage;
|
|
676
665
|
const family = action === 'analysis' ? 'analysis' : action;
|
|
677
|
-
const artifactContext =
|
|
666
|
+
const artifactContext = resolveArtifactContextForResolvedTask(resolved, family, {
|
|
678
667
|
repoRoot: resolved.repoRoot
|
|
679
668
|
});
|
|
680
669
|
if (artifactContext.status !== 'ready' || !artifactContext.selection) {
|
|
@@ -700,6 +689,12 @@ function routeOrchestration(taskRef, options = {}) {
|
|
|
700
689
|
};
|
|
701
690
|
return { status: 'running', changed: false, taskId: resolved.taskId, run, next, error: null };
|
|
702
691
|
}
|
|
692
|
+
function routeOrchestration(taskRef, options = {}) {
|
|
693
|
+
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
694
|
+
if (!resolved.ok)
|
|
695
|
+
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
696
|
+
return routeResolvedTask(taskRef, resolved, options);
|
|
697
|
+
}
|
|
703
698
|
function statusOrchestration(taskRef, options = {}) {
|
|
704
699
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
705
700
|
if (!resolved.ok)
|
|
@@ -743,7 +738,7 @@ function validateDelegationRun(taskRef, taskId, run, options) {
|
|
|
743
738
|
}
|
|
744
739
|
return null;
|
|
745
740
|
}
|
|
746
|
-
function
|
|
741
|
+
function prepareOrchestrationDelegation(taskRef, input, options = {}) {
|
|
747
742
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
748
743
|
if (!resolved.ok)
|
|
749
744
|
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
@@ -763,7 +758,7 @@ function prepareOrchestrationDelegationUnlocked(taskRef, input, options = {}) {
|
|
|
763
758
|
if (runFailure)
|
|
764
759
|
return runFailure;
|
|
765
760
|
const activeRun = run;
|
|
766
|
-
const routed =
|
|
761
|
+
const routed = routeResolvedTask(taskRef, resolved, options);
|
|
767
762
|
if (!routed.next)
|
|
768
763
|
return routed;
|
|
769
764
|
const next = routed.next;
|
|
@@ -797,20 +792,7 @@ function prepareOrchestrationDelegationUnlocked(taskRef, input, options = {}) {
|
|
|
797
792
|
saveRun(resolved.taskDir, updated);
|
|
798
793
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next, error: null };
|
|
799
794
|
}
|
|
800
|
-
function
|
|
801
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
802
|
-
if (!resolved.ok)
|
|
803
|
-
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
804
|
-
try {
|
|
805
|
-
return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-orchestration.prepare.task', () => prepareOrchestrationDelegationUnlocked(taskRef, input, options));
|
|
806
|
-
}
|
|
807
|
-
catch (error) {
|
|
808
|
-
if (error instanceof TaskExecutionLockError)
|
|
809
|
-
return failed(error.code, error.message, resolved.taskId);
|
|
810
|
-
throw error;
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
function dispatchOrchestrationDelegationUnlocked(taskRef, options = {}) {
|
|
795
|
+
function dispatchOrchestrationDelegation(taskRef, options = {}) {
|
|
814
796
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
815
797
|
if (!resolved.ok)
|
|
816
798
|
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
@@ -830,19 +812,6 @@ function dispatchOrchestrationDelegationUnlocked(taskRef, options = {}) {
|
|
|
830
812
|
saveRun(resolved.taskDir, updated);
|
|
831
813
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
832
814
|
}
|
|
833
|
-
function dispatchOrchestrationDelegation(taskRef, options = {}) {
|
|
834
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
835
|
-
if (!resolved.ok)
|
|
836
|
-
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
837
|
-
try {
|
|
838
|
-
return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-orchestration.dispatch.task', () => dispatchOrchestrationDelegationUnlocked(taskRef, options));
|
|
839
|
-
}
|
|
840
|
-
catch (error) {
|
|
841
|
-
if (error instanceof TaskExecutionLockError)
|
|
842
|
-
return failed(error.code, error.message, resolved.taskId);
|
|
843
|
-
throw error;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
815
|
function matchingDelegations(predicate, options) {
|
|
847
816
|
const taskId = options.taskId;
|
|
848
817
|
if (taskId === undefined || taskId === '') {
|
|
@@ -852,7 +821,7 @@ function matchingDelegations(predicate, options) {
|
|
|
852
821
|
return { ok: false, error: failed('ORCHESTRATION_TASK_ID_INVALID', 'taskId must be a canonical TASK-id') };
|
|
853
822
|
}
|
|
854
823
|
const repoRoot = options.repoRoot ?? process.cwd();
|
|
855
|
-
const taskDir = path.join(repoRoot, '
|
|
824
|
+
const taskDir = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', taskId);
|
|
856
825
|
const run = readRun(taskDir, options);
|
|
857
826
|
const matches = run && run.status === 'running' && run.pendingDelegation && predicate(run.pendingDelegation)
|
|
858
827
|
? [{ taskId, run }]
|
|
@@ -1033,7 +1002,7 @@ function recoverPreparedOrchestrationDelegation(taskRef, options = {}) {
|
|
|
1033
1002
|
if (!resolved.ok)
|
|
1034
1003
|
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1035
1004
|
try {
|
|
1036
|
-
return
|
|
1005
|
+
return (() => {
|
|
1037
1006
|
const run = readRun(resolved.taskDir, options);
|
|
1038
1007
|
const receipt = run?.pendingDelegation;
|
|
1039
1008
|
if (!run || !receipt) {
|
|
@@ -1073,11 +1042,9 @@ function recoverPreparedOrchestrationDelegation(taskRef, options = {}) {
|
|
|
1073
1042
|
}, options.now);
|
|
1074
1043
|
saveRun(resolved.taskDir, updated);
|
|
1075
1044
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
1076
|
-
});
|
|
1045
|
+
})();
|
|
1077
1046
|
}
|
|
1078
1047
|
catch (error) {
|
|
1079
|
-
if (error instanceof TaskExecutionLockError)
|
|
1080
|
-
return failed(error.code, error.message, resolved.taskId);
|
|
1081
1048
|
return failed('ORCHESTRATION_PREPARED_RECOVERY_FAILED', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
1082
1049
|
}
|
|
1083
1050
|
}
|
|
@@ -1088,7 +1055,7 @@ function recoveryReceiptMatches(receipt, event) {
|
|
|
1088
1055
|
&& receipt.childId === event.childId
|
|
1089
1056
|
&& normalizeAgentToken(event.startedAgent) === normalizeAgentToken(receipt.client);
|
|
1090
1057
|
}
|
|
1091
|
-
function
|
|
1058
|
+
function recoverActivatedOrchestrationDelegation(taskRef, event, options = {}) {
|
|
1092
1059
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1093
1060
|
if (!resolved.ok)
|
|
1094
1061
|
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
@@ -1204,7 +1171,7 @@ function sealOrchestrationDelegation(taskRef, event, expected, options = {}, bef
|
|
|
1204
1171
|
const resolved = resolveTaskRef(taskRef, { repoRoot: orchestrationOptions.repoRoot });
|
|
1205
1172
|
if (!resolved.ok)
|
|
1206
1173
|
return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1207
|
-
return
|
|
1174
|
+
return (() => {
|
|
1208
1175
|
const run = readRun(resolved.taskDir, orchestrationOptions);
|
|
1209
1176
|
if (!run?.pendingDelegation)
|
|
1210
1177
|
return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
@@ -1226,7 +1193,7 @@ function sealOrchestrationDelegation(taskRef, event, expected, options = {}, bef
|
|
|
1226
1193
|
const updated = withUpdatedRun(current, { pendingDelegation: result.receipt });
|
|
1227
1194
|
saveRun(resolved.taskDir, updated);
|
|
1228
1195
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
1229
|
-
});
|
|
1196
|
+
})();
|
|
1230
1197
|
}
|
|
1231
1198
|
function advanceOrchestration(taskRef, options = {}) {
|
|
1232
1199
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
@@ -1262,5 +1229,5 @@ function pauseOrchestration(taskRef, code, message, recoverable, options = {}) {
|
|
|
1262
1229
|
saveRun(resolved.taskDir, updated);
|
|
1263
1230
|
return { status: 'paused', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
1264
1231
|
}
|
|
1265
|
-
export { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, awaitOrchestrationDelegationActivation, advanceOrchestration, beginOrResumeOrchestration, commitOrchestrationStageCompletion, completeOrchestrationStage, dispatchOrchestrationDelegation, inspectOrchestrationStage, hasActivatableOrchestrationDelegation, hasSealableOrchestrationDelegation, OrchestrationStateError, orchestrationPath, readDelegationAdapterEvidence, mutateDelegationAdapterEvidence,
|
|
1232
|
+
export { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, awaitOrchestrationDelegationActivation, advanceOrchestration, beginOrResumeOrchestration, commitOrchestrationStageCompletion, completeOrchestrationStage, dispatchOrchestrationDelegation, inspectOrchestrationStage, hasActivatableOrchestrationDelegation, hasSealableOrchestrationDelegation, OrchestrationStateError, orchestrationPath, readDelegationAdapterEvidence, mutateDelegationAdapterEvidence, pauseMatchingOrchestrationDelegation, pauseOrchestration, planOrchestrationStageCompletion, prepareOrchestrationDelegation, readRun, reconcileMatchingOrchestrationDelegation, recoverPreparedOrchestrationDelegation, recoverActivatedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, statusOrchestration, };
|
|
1266
1233
|
//# sourceMappingURL=orchestration.js.map
|
|
@@ -234,8 +234,7 @@ async function replayPullRequestSummary(taskId, operation, agent, cwd, client) {
|
|
|
234
234
|
...(summary.manualValidation ? { manualValidation: summary.manualValidation } : {}),
|
|
235
235
|
primaryResult: 'no_op',
|
|
236
236
|
strict: true,
|
|
237
|
-
skipQueue: true
|
|
238
|
-
lockAlreadyHeld: true
|
|
237
|
+
skipQueue: true
|
|
239
238
|
});
|
|
240
239
|
if ((replayed.status === 'applied' || replayed.status === 'no-op') && !replayed.error && replayed.warnings.length === 0) {
|
|
241
240
|
return platformResult(replayed.status, { changed: replayed.changed });
|
|
@@ -3,10 +3,12 @@ import path from 'node:path';
|
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
4
|
import { normalizeShortIdInput, resolveShortIdReadOnly } from './short-id.js';
|
|
5
5
|
import { parseTaskFrontmatter } from './frontmatter.js';
|
|
6
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.js';
|
|
6
7
|
const TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
|
|
7
8
|
// Flat-structured workspace dirs that hold tasks under `{dir}/{taskId}/task.md`.
|
|
8
9
|
// Note: `archive` uses a three-level YYYY/MM/DD layout and is handled separately.
|
|
9
10
|
const FLAT_WORKSPACE_DIRS = ['active', 'blocked', 'completed'];
|
|
11
|
+
function taskRoot(repoRoot) { return resolveProjectTaskWorkspaceRoot(repoRoot); }
|
|
10
12
|
function detectRepoRoot() {
|
|
11
13
|
try {
|
|
12
14
|
return execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
@@ -40,12 +42,12 @@ function listSortedNumeric(dir, width) {
|
|
|
40
42
|
.sort()
|
|
41
43
|
.reverse();
|
|
42
44
|
}
|
|
43
|
-
function findInArchive(
|
|
44
|
-
// archive-tasks stores local material at
|
|
45
|
+
function findInArchive(workspaceRoot, taskId) {
|
|
46
|
+
// archive-tasks stores local material at the project task workspace archive/YYYY/MM/DD/{taskId}/local/task.md
|
|
45
47
|
// where YYYY/MM/DD comes from completed_at (or updated_at fallback) — NOT from
|
|
46
48
|
// the task id's creation date. So we cannot derive the path from taskId alone;
|
|
47
49
|
// walk the bounded YYYY/MM/DD tree instead. Newest-first to favor recent archives.
|
|
48
|
-
const archiveDir = path.join(
|
|
50
|
+
const archiveDir = path.join(workspaceRoot, 'archive');
|
|
49
51
|
for (const year of listSortedNumeric(archiveDir, 4)) {
|
|
50
52
|
const yearDir = path.join(archiveDir, year);
|
|
51
53
|
for (const month of listSortedNumeric(yearDir, 2)) {
|
|
@@ -59,13 +61,13 @@ function findInArchive(repoRoot, taskId) {
|
|
|
59
61
|
}
|
|
60
62
|
return null;
|
|
61
63
|
}
|
|
62
|
-
function findTaskMd(
|
|
64
|
+
function findTaskMd(workspaceRoot, taskId) {
|
|
63
65
|
for (const sub of FLAT_WORKSPACE_DIRS) {
|
|
64
|
-
const candidate = path.join(
|
|
66
|
+
const candidate = path.join(workspaceRoot, sub, taskId, 'task.md');
|
|
65
67
|
if (fs.existsSync(candidate))
|
|
66
68
|
return { taskMdPath: candidate, state: sub };
|
|
67
69
|
}
|
|
68
|
-
const archived = findInArchive(
|
|
70
|
+
const archived = findInArchive(workspaceRoot, taskId);
|
|
69
71
|
return archived ? { taskMdPath: archived, state: 'archive' } : null;
|
|
70
72
|
}
|
|
71
73
|
/**
|
|
@@ -76,8 +78,9 @@ function findTaskMd(repoRoot, taskId) {
|
|
|
76
78
|
*/
|
|
77
79
|
function enumerateTaskDirs(repoRoot) {
|
|
78
80
|
const out = [];
|
|
81
|
+
const workspaceRoot = taskRoot(repoRoot);
|
|
79
82
|
for (const sub of FLAT_WORKSPACE_DIRS) {
|
|
80
|
-
const base = path.join(
|
|
83
|
+
const base = path.join(workspaceRoot, sub);
|
|
81
84
|
if (!fs.existsSync(base))
|
|
82
85
|
continue;
|
|
83
86
|
for (const entry of fs.readdirSync(base).sort()) {
|
|
@@ -98,6 +101,7 @@ function enumerateTaskDirs(repoRoot) {
|
|
|
98
101
|
*/
|
|
99
102
|
function enumerateAllTaskDirs(repoRoot) {
|
|
100
103
|
const out = [];
|
|
104
|
+
const workspaceRoot = taskRoot(repoRoot);
|
|
101
105
|
const seen = new Map();
|
|
102
106
|
const add = (taskId, taskDir, state) => {
|
|
103
107
|
if (!TASK_ID_RE.test(taskId))
|
|
@@ -116,13 +120,13 @@ function enumerateAllTaskDirs(repoRoot) {
|
|
|
116
120
|
out.push({ taskId, taskDir, state });
|
|
117
121
|
};
|
|
118
122
|
for (const state of FLAT_WORKSPACE_DIRS) {
|
|
119
|
-
const base = path.join(
|
|
123
|
+
const base = path.join(workspaceRoot, state);
|
|
120
124
|
if (!fs.existsSync(base))
|
|
121
125
|
continue;
|
|
122
126
|
for (const taskId of fs.readdirSync(base).sort())
|
|
123
127
|
add(taskId, path.join(base, taskId), state);
|
|
124
128
|
}
|
|
125
|
-
const archive = path.join(
|
|
129
|
+
const archive = path.join(workspaceRoot, 'archive');
|
|
126
130
|
for (const year of listSortedNumeric(archive, 4).reverse()) {
|
|
127
131
|
const yearDir = path.join(archive, year);
|
|
128
132
|
for (const month of listSortedNumeric(yearDir, 2).reverse()) {
|
|
@@ -137,8 +141,9 @@ function enumerateAllTaskDirs(repoRoot) {
|
|
|
137
141
|
return out;
|
|
138
142
|
}
|
|
139
143
|
function locateHotTaskDirs(repoRoot, taskId) {
|
|
144
|
+
const workspaceRoot = taskRoot(repoRoot);
|
|
140
145
|
return FLAT_WORKSPACE_DIRS.flatMap((state) => {
|
|
141
|
-
const taskDir = path.join(
|
|
146
|
+
const taskDir = path.join(workspaceRoot, state, taskId);
|
|
142
147
|
const taskMdPath = path.join(taskDir, 'task.md');
|
|
143
148
|
return fs.existsSync(taskMdPath) ? [{ taskId, taskDir, taskMdPath, state }] : [];
|
|
144
149
|
});
|
|
@@ -203,7 +208,7 @@ function resolveTaskRef(arg, options = {}) {
|
|
|
203
208
|
}
|
|
204
209
|
taskId = shortResult.taskId;
|
|
205
210
|
}
|
|
206
|
-
const located = findTaskMd(repoRoot, taskId);
|
|
211
|
+
const located = findTaskMd(taskRoot(repoRoot), taskId);
|
|
207
212
|
if (!located) {
|
|
208
213
|
return {
|
|
209
214
|
ok: false,
|
|
@@ -255,7 +260,7 @@ function resolveTaskContext(taskRef, options = {}) {
|
|
|
255
260
|
taskId: null
|
|
256
261
|
};
|
|
257
262
|
}
|
|
258
|
-
const activeDir = path.join(repoRoot, '
|
|
263
|
+
const activeDir = path.join(taskRoot(repoRoot), 'active');
|
|
259
264
|
const matches = [];
|
|
260
265
|
if (fs.existsSync(activeDir)) {
|
|
261
266
|
for (const entry of fs.readdirSync(activeDir).sort()) {
|
|
@@ -8,7 +8,6 @@ import { finalizeReviewSummaryContent } from './review-artifacts.js';
|
|
|
8
8
|
import { inspectDecisionDetailDuplicates } from './decision-details.js';
|
|
9
9
|
import { resolveTaskRef } from './resolve-ref.js';
|
|
10
10
|
import { validateLifecycleExecution } from './lifecycle-execution.js';
|
|
11
|
-
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
|
|
12
11
|
import { getArtifactSchema } from './artifact-schema.js';
|
|
13
12
|
import { validateQualificationAudit } from './qualification-audit.js';
|
|
14
13
|
import { canonicalSemanticDigest, inspectArtifactContract, sha256Content } from './artifact-operations.js';
|
|
@@ -47,7 +46,7 @@ function preflightFailed(request, code, message, taskId = null, extra = {}) {
|
|
|
47
46
|
};
|
|
48
47
|
}
|
|
49
48
|
/** Validate the current review draft before any finding-ledger write. */
|
|
50
|
-
function
|
|
49
|
+
function preflightReviewSummary(request, options = {}) {
|
|
51
50
|
const stage = request.stage;
|
|
52
51
|
const spec = STAGES[stage];
|
|
53
52
|
if (!spec)
|
|
@@ -106,21 +105,6 @@ function preflightReviewSummaryUnlocked(request, options = {}) {
|
|
|
106
105
|
status: 'passed', changed: false, error: null
|
|
107
106
|
};
|
|
108
107
|
}
|
|
109
|
-
function preflightReviewSummary(request, options = {}) {
|
|
110
|
-
if (request.dryRun || options.lockAlreadyHeld)
|
|
111
|
-
return preflightReviewSummaryUnlocked(request, options);
|
|
112
|
-
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
113
|
-
if (!resolved.ok)
|
|
114
|
-
return preflightReviewSummaryUnlocked(request, options);
|
|
115
|
-
try {
|
|
116
|
-
return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-review.preflight', () => preflightReviewSummaryUnlocked(request, { ...options, lockAlreadyHeld: true }));
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
if (!(error instanceof TaskExecutionLockError))
|
|
120
|
-
throw error;
|
|
121
|
-
return preflightFailed(request, 'REVIEW_PROVENANCE_INVALID', `${error.code}: ${error.message}`, resolved.taskId);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
108
|
/** Prepare domain validation, summary bytes and provenance before any publication. */
|
|
125
109
|
function prepareReviewSummaryCandidate(request, artifactContent, options = {}) {
|
|
126
110
|
let taskId = null;
|
|
@@ -208,7 +192,6 @@ function prepareReviewSummaryCandidate(request, artifactContent, options = {}) {
|
|
|
208
192
|
operations: transformed.changed ? [{ kind: 'artifact', artifact: request.artifact, operation: 'update' }] : [],
|
|
209
193
|
error: null
|
|
210
194
|
},
|
|
211
|
-
lockAlreadyHeld: options.lockAlreadyHeld
|
|
212
195
|
};
|
|
213
196
|
}
|
|
214
197
|
function commitReviewSummaryProvenance(prepared, repoRoot, options = {}) {
|
|
@@ -230,7 +213,7 @@ function replaceCurrentArtifactAtomically(file, content) {
|
|
|
230
213
|
}
|
|
231
214
|
}
|
|
232
215
|
}
|
|
233
|
-
function
|
|
216
|
+
function finalizeReviewSummary(request, options = {}) {
|
|
234
217
|
const spec = STAGES[request.stage];
|
|
235
218
|
if (!spec || !request.taskRef || !request.artifact)
|
|
236
219
|
return prepareReviewSummaryCandidate(request, '', options).result;
|
|
@@ -267,21 +250,5 @@ function finalizeReviewSummaryUnlocked(request, options = {}) {
|
|
|
267
250
|
return failed(request, 'REVIEW_RECOVERY_COMMIT_FAILED', `cannot update current review artifact: ${error instanceof Error ? error.message : String(error)}`, resolved.taskId);
|
|
268
251
|
}
|
|
269
252
|
}
|
|
270
|
-
function finalizeReviewSummary(request, options = {}) {
|
|
271
|
-
const effectiveOptions = options;
|
|
272
|
-
if (request.dryRun || options.lockAlreadyHeld)
|
|
273
|
-
return finalizeReviewSummaryUnlocked(request, effectiveOptions);
|
|
274
|
-
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
275
|
-
if (!resolved.ok)
|
|
276
|
-
return finalizeReviewSummaryUnlocked(request, effectiveOptions);
|
|
277
|
-
try {
|
|
278
|
-
return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-review.finalize-summary', () => finalizeReviewSummaryUnlocked(request, { ...effectiveOptions, lockAlreadyHeld: true }));
|
|
279
|
-
}
|
|
280
|
-
catch (error) {
|
|
281
|
-
if (!(error instanceof TaskExecutionLockError))
|
|
282
|
-
throw error;
|
|
283
|
-
return failed(request, 'REVIEW_PROVENANCE_INVALID', `${error.code}: ${error.message}`, resolved.taskId);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
253
|
export { finalizeReviewSummary, preflightReviewSummary, prepareReviewSummaryCandidate, commitReviewSummaryProvenance };
|
|
287
254
|
//# sourceMappingURL=review-finalization.js.map
|
|
@@ -23,7 +23,9 @@ export function inspectReviewIdentity(taskDir, reportContent, repositoryRoot) {
|
|
|
23
23
|
}
|
|
24
24
|
try {
|
|
25
25
|
const metadata = parseTypedTaskFrontmatter(fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8'));
|
|
26
|
-
const taskRepositoryRoot =
|
|
26
|
+
const taskRepositoryRoot = repositoryRoot
|
|
27
|
+
? fs.realpathSync.native(repositoryRoot)
|
|
28
|
+
: git(taskDir, ['rev-parse', '--show-toplevel']);
|
|
27
29
|
const branch = String(metadata.branch ?? '').trim();
|
|
28
30
|
const gitRoot = branch ? resolveBranchWorktree(taskRepositoryRoot, branch) : taskRepositoryRoot;
|
|
29
31
|
if (!gitRoot)
|