@fitlab-ai/agent-infra 0.11.15 → 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-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-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 +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 +3 -10
- 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 +17 -22
- 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 +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 +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 +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-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-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 +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 +3 -26
- 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 +16 -24
- 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 +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 +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 +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 +7 -7
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +8 -8
- 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 +1 -1
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +1 -1
- 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/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 +3 -3
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/watch-pr/config/verify.json +0 -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/task/task-execution-lock.js +0 -250
- package/lib/task/task-execution-lock.ts +0 -320
|
@@ -9,6 +9,7 @@ import { parseReviewSummary } from './review-artifacts.ts';
|
|
|
9
9
|
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
|
|
10
10
|
import type { LedgerDocument } from './ledger.ts';
|
|
11
11
|
import { resolveTaskRef, TASK_ID_RE } from './resolve-ref.ts';
|
|
12
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
|
|
12
13
|
import {
|
|
13
14
|
activateDelegation,
|
|
14
15
|
abortActivatedDelegation,
|
|
@@ -48,14 +49,13 @@ import {
|
|
|
48
49
|
import type { RepositorySnapshot } from './workspace-snapshot.ts';
|
|
49
50
|
import type { WorkspaceSnapshotContext } from './workspace-snapshot.ts';
|
|
50
51
|
import { assertGitRepositoryBinding } from '../git/worktree-identity.ts';
|
|
51
|
-
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.ts';
|
|
52
52
|
import { extractReviewBaseline, extractReviewDiffBase, extractReviewTargetHead, extractReviewedHead } from './review-fingerprint.ts';
|
|
53
53
|
import { resolveDeliveryTarget, resolveDiffBase, resolveTargetHead } from './delivery-target.ts';
|
|
54
54
|
import { buildLifecycleFacts, canStart, recommendNext } from './capabilities.ts';
|
|
55
55
|
import { hasOpenLifecycleExecution } from './activity-log.ts';
|
|
56
56
|
import type { LifecycleAction, LifecycleFacts } from './capabilities.ts';
|
|
57
57
|
import { normalizeAgentToken } from '../agent-clients/tokens.ts';
|
|
58
|
-
import {
|
|
58
|
+
import { resolveArtifactContextForResolvedTask } from './artifact-lifecycle.ts';
|
|
59
59
|
|
|
60
60
|
type OrchestrationStatus = 'running' | 'paused' | 'completed';
|
|
61
61
|
type ModelPolicySource = Readonly<{
|
|
@@ -441,19 +441,7 @@ function mutateDelegationAdapterEvidence(
|
|
|
441
441
|
): unknown {
|
|
442
442
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
443
443
|
if (!resolved.ok) throw new Error(`${resolved.code}: ${resolved.message}`);
|
|
444
|
-
return mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
function mutateDelegationAdapterEvidenceWithinTaskLock(
|
|
448
|
-
taskRef: string,
|
|
449
|
-
receiptId: string,
|
|
450
|
-
adapterId: AgentClientId,
|
|
451
|
-
mutate: (current: unknown) => unknown,
|
|
452
|
-
options: OrchestrationOptions = {}
|
|
453
|
-
): unknown {
|
|
454
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
455
|
-
if (!resolved.ok) throw new Error(`${resolved.code}: ${resolved.message}`);
|
|
456
|
-
return mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options, true);
|
|
444
|
+
return mutateDelegationAdapterEvidenceAtResolved(resolved, receiptId, adapterId, mutate, options);
|
|
457
445
|
}
|
|
458
446
|
|
|
459
447
|
function mutateDelegationAdapterEvidenceAtResolved(
|
|
@@ -461,8 +449,7 @@ function mutateDelegationAdapterEvidenceAtResolved(
|
|
|
461
449
|
receiptId: string,
|
|
462
450
|
adapterId: AgentClientId,
|
|
463
451
|
mutate: (current: unknown) => unknown,
|
|
464
|
-
options: OrchestrationOptions
|
|
465
|
-
taskLockHeld: boolean
|
|
452
|
+
options: OrchestrationOptions
|
|
466
453
|
): unknown {
|
|
467
454
|
const update = () => {
|
|
468
455
|
try {
|
|
@@ -494,9 +481,7 @@ function mutateDelegationAdapterEvidenceAtResolved(
|
|
|
494
481
|
}
|
|
495
482
|
};
|
|
496
483
|
let mutationError: unknown;
|
|
497
|
-
const result =
|
|
498
|
-
? update()
|
|
499
|
-
: withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `agent-adapter.${adapterId}.evidence`, update);
|
|
484
|
+
const result = update();
|
|
500
485
|
if (mutationError) throw mutationError;
|
|
501
486
|
return result;
|
|
502
487
|
}
|
|
@@ -733,9 +718,13 @@ function routeFromFacts(facts: LifecycleFacts): Omit<OrchestrationNext, 'request
|
|
|
733
718
|
return { action: command, role, stage: action };
|
|
734
719
|
}
|
|
735
720
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
721
|
+
type ResolvedTaskRef = Extract<ReturnType<typeof resolveTaskRef>, { ok: true }>;
|
|
722
|
+
|
|
723
|
+
function routeResolvedTask(
|
|
724
|
+
taskRef: string,
|
|
725
|
+
resolved: ResolvedTaskRef,
|
|
726
|
+
options: OrchestrationOptions
|
|
727
|
+
): OrchestrationResult {
|
|
739
728
|
let gitRoot: string;
|
|
740
729
|
try {
|
|
741
730
|
gitRoot = gitRootFor(resolved.repoRoot, options);
|
|
@@ -772,7 +761,8 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
772
761
|
resolved.taskDir,
|
|
773
762
|
content,
|
|
774
763
|
resolved.state,
|
|
775
|
-
hasOpenLifecycleExecution(content) || Boolean(run?.pendingDelegation)
|
|
764
|
+
hasOpenLifecycleExecution(content) || Boolean(run?.pendingDelegation),
|
|
765
|
+
resolved.repoRoot
|
|
776
766
|
);
|
|
777
767
|
if (!facts.ok) return failed('ORCHESTRATION_CAPABILITY_FACTS_INVALID', facts.message, resolved.taskId);
|
|
778
768
|
const routed = routeFromFacts(facts.facts);
|
|
@@ -864,7 +854,7 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
864
854
|
}
|
|
865
855
|
const action = routed.stage as LifecycleAction;
|
|
866
856
|
const family = action === 'analysis' ? 'analysis' : action;
|
|
867
|
-
const artifactContext =
|
|
857
|
+
const artifactContext = resolveArtifactContextForResolvedTask(resolved, family, {
|
|
868
858
|
repoRoot: resolved.repoRoot
|
|
869
859
|
});
|
|
870
860
|
if (artifactContext.status !== 'ready' || !artifactContext.selection) {
|
|
@@ -898,6 +888,12 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
898
888
|
return { status: 'running', changed: false, taskId: resolved.taskId, run, next, error: null };
|
|
899
889
|
}
|
|
900
890
|
|
|
891
|
+
function routeOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
892
|
+
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
893
|
+
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
894
|
+
return routeResolvedTask(taskRef, resolved, options);
|
|
895
|
+
}
|
|
896
|
+
|
|
901
897
|
function statusOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
902
898
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
903
899
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
@@ -952,7 +948,7 @@ function validateDelegationRun(
|
|
|
952
948
|
return null;
|
|
953
949
|
}
|
|
954
950
|
|
|
955
|
-
function
|
|
951
|
+
function prepareOrchestrationDelegation(
|
|
956
952
|
taskRef: string,
|
|
957
953
|
input: Readonly<{
|
|
958
954
|
client: AgentClientId;
|
|
@@ -978,7 +974,7 @@ function prepareOrchestrationDelegationUnlocked(
|
|
|
978
974
|
const runFailure = validateDelegationRun(taskRef, resolved.taskId, run, options);
|
|
979
975
|
if (runFailure) return runFailure;
|
|
980
976
|
const activeRun = run!;
|
|
981
|
-
const routed =
|
|
977
|
+
const routed = routeResolvedTask(taskRef, resolved, options);
|
|
982
978
|
if (!routed.next) return routed;
|
|
983
979
|
const next = routed.next;
|
|
984
980
|
const policyFailure = validatePreparedModelPolicy(resolved.taskId, activeRun, next, input);
|
|
@@ -1010,31 +1006,7 @@ function prepareOrchestrationDelegationUnlocked(
|
|
|
1010
1006
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next, error: null };
|
|
1011
1007
|
}
|
|
1012
1008
|
|
|
1013
|
-
function
|
|
1014
|
-
taskRef: string,
|
|
1015
|
-
input: Readonly<{
|
|
1016
|
-
client: AgentClientId;
|
|
1017
|
-
requestedModel?: string;
|
|
1018
|
-
requestedReasoningEffort?: string;
|
|
1019
|
-
}>,
|
|
1020
|
-
options: OrchestrationOptions = {}
|
|
1021
|
-
): OrchestrationResult {
|
|
1022
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1023
|
-
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1024
|
-
try {
|
|
1025
|
-
return withTaskExecutionLock(
|
|
1026
|
-
resolved.repoRoot,
|
|
1027
|
-
resolved.taskId,
|
|
1028
|
-
'task-orchestration.prepare.task',
|
|
1029
|
-
() => prepareOrchestrationDelegationUnlocked(taskRef, input, options)
|
|
1030
|
-
);
|
|
1031
|
-
} catch (error) {
|
|
1032
|
-
if (error instanceof TaskExecutionLockError) return failed(error.code, error.message, resolved.taskId);
|
|
1033
|
-
throw error;
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
function dispatchOrchestrationDelegationUnlocked(
|
|
1009
|
+
function dispatchOrchestrationDelegation(
|
|
1038
1010
|
taskRef: string,
|
|
1039
1011
|
options: OrchestrationOptions = {}
|
|
1040
1012
|
): OrchestrationResult {
|
|
@@ -1055,25 +1027,6 @@ function dispatchOrchestrationDelegationUnlocked(
|
|
|
1055
1027
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
1056
1028
|
}
|
|
1057
1029
|
|
|
1058
|
-
function dispatchOrchestrationDelegation(
|
|
1059
|
-
taskRef: string,
|
|
1060
|
-
options: OrchestrationOptions = {}
|
|
1061
|
-
): OrchestrationResult {
|
|
1062
|
-
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1063
|
-
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1064
|
-
try {
|
|
1065
|
-
return withTaskExecutionLock(
|
|
1066
|
-
resolved.repoRoot,
|
|
1067
|
-
resolved.taskId,
|
|
1068
|
-
'task-orchestration.dispatch.task',
|
|
1069
|
-
() => dispatchOrchestrationDelegationUnlocked(taskRef, options)
|
|
1070
|
-
);
|
|
1071
|
-
} catch (error) {
|
|
1072
|
-
if (error instanceof TaskExecutionLockError) return failed(error.code, error.message, resolved.taskId);
|
|
1073
|
-
throw error;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
1030
|
type MatchingDelegationsResult =
|
|
1078
1031
|
| Readonly<{ ok: true; matches: readonly { taskId: string; run: OrchestrationRun }[] }>
|
|
1079
1032
|
| Readonly<{ ok: false; error: OrchestrationResult }>;
|
|
@@ -1090,7 +1043,7 @@ function matchingDelegations(
|
|
|
1090
1043
|
return { ok: false, error: failed('ORCHESTRATION_TASK_ID_INVALID', 'taskId must be a canonical TASK-id') };
|
|
1091
1044
|
}
|
|
1092
1045
|
const repoRoot = options.repoRoot ?? process.cwd();
|
|
1093
|
-
const taskDir = path.join(repoRoot, '
|
|
1046
|
+
const taskDir = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', taskId);
|
|
1094
1047
|
const run = readRun(taskDir, options);
|
|
1095
1048
|
const matches = run && run.status === 'running' && run.pendingDelegation && predicate(run.pendingDelegation)
|
|
1096
1049
|
? [{ taskId, run }]
|
|
@@ -1385,7 +1338,7 @@ function recoverPreparedOrchestrationDelegation(
|
|
|
1385
1338
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1386
1339
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1387
1340
|
try {
|
|
1388
|
-
return
|
|
1341
|
+
return (() => {
|
|
1389
1342
|
const run = readRun(resolved.taskDir, options);
|
|
1390
1343
|
const receipt = run?.pendingDelegation;
|
|
1391
1344
|
if (!run || !receipt) {
|
|
@@ -1430,9 +1383,8 @@ function recoverPreparedOrchestrationDelegation(
|
|
|
1430
1383
|
}, options.now);
|
|
1431
1384
|
saveRun(resolved.taskDir, updated);
|
|
1432
1385
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
1433
|
-
});
|
|
1386
|
+
})();
|
|
1434
1387
|
} catch (error) {
|
|
1435
|
-
if (error instanceof TaskExecutionLockError) return failed(error.code, error.message, resolved.taskId);
|
|
1436
1388
|
return failed(
|
|
1437
1389
|
'ORCHESTRATION_PREPARED_RECOVERY_FAILED',
|
|
1438
1390
|
error instanceof Error ? error.message : String(error),
|
|
@@ -1462,7 +1414,7 @@ function recoveryReceiptMatches(
|
|
|
1462
1414
|
&& normalizeAgentToken(event.startedAgent) === normalizeAgentToken(receipt.client);
|
|
1463
1415
|
}
|
|
1464
1416
|
|
|
1465
|
-
function
|
|
1417
|
+
function recoverActivatedOrchestrationDelegation(
|
|
1466
1418
|
taskRef: string,
|
|
1467
1419
|
event: ActivatedRecoveryEvent,
|
|
1468
1420
|
options: OrchestrationOptions = {}
|
|
@@ -1598,7 +1550,7 @@ function sealOrchestrationDelegation(
|
|
|
1598
1550
|
const orchestrationOptions = options;
|
|
1599
1551
|
const resolved = resolveTaskRef(taskRef, { repoRoot: orchestrationOptions.repoRoot });
|
|
1600
1552
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1601
|
-
return
|
|
1553
|
+
return (() => {
|
|
1602
1554
|
const run = readRun(resolved.taskDir, orchestrationOptions);
|
|
1603
1555
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1604
1556
|
if (expected && (run.runId !== expected.runId || run.pendingDelegation.id !== expected.receiptId)) {
|
|
@@ -1616,7 +1568,7 @@ function sealOrchestrationDelegation(
|
|
|
1616
1568
|
const updated = withUpdatedRun(current, { pendingDelegation: result.receipt });
|
|
1617
1569
|
saveRun(resolved.taskDir, updated);
|
|
1618
1570
|
return { status: 'running', changed: true, taskId: resolved.taskId, run: updated, next: null, error: null };
|
|
1619
|
-
});
|
|
1571
|
+
})();
|
|
1620
1572
|
}
|
|
1621
1573
|
|
|
1622
1574
|
function advanceOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
@@ -1672,7 +1624,6 @@ export {
|
|
|
1672
1624
|
orchestrationPath,
|
|
1673
1625
|
readDelegationAdapterEvidence,
|
|
1674
1626
|
mutateDelegationAdapterEvidence,
|
|
1675
|
-
mutateDelegationAdapterEvidenceWithinTaskLock,
|
|
1676
1627
|
pauseMatchingOrchestrationDelegation,
|
|
1677
1628
|
pauseOrchestration,
|
|
1678
1629
|
planOrchestrationStageCompletion,
|
|
@@ -1680,7 +1631,7 @@ export {
|
|
|
1680
1631
|
readRun,
|
|
1681
1632
|
reconcileMatchingOrchestrationDelegation,
|
|
1682
1633
|
recoverPreparedOrchestrationDelegation,
|
|
1683
|
-
|
|
1634
|
+
recoverActivatedOrchestrationDelegation,
|
|
1684
1635
|
routeOrchestration,
|
|
1685
1636
|
sealMatchingOrchestrationDelegation,
|
|
1686
1637
|
sealOrchestrationDelegation,
|
|
@@ -222,8 +222,7 @@ async function replayPullRequestSummary(taskId: string, operation: ReturnType<ty
|
|
|
222
222
|
...(summary.manualValidation ? { manualValidation: summary.manualValidation } : {}),
|
|
223
223
|
primaryResult: 'no_op',
|
|
224
224
|
strict: true,
|
|
225
|
-
skipQueue: true
|
|
226
|
-
lockAlreadyHeld: true
|
|
225
|
+
skipQueue: true
|
|
227
226
|
});
|
|
228
227
|
if ((replayed.status === 'applied' || replayed.status === 'no-op') && !replayed.error && replayed.warnings.length === 0) {
|
|
229
228
|
return platformResult(replayed.status, { changed: replayed.changed });
|
package/lib/task/resolve-ref.ts
CHANGED
|
@@ -3,12 +3,15 @@ import path from 'node:path';
|
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
4
|
import { normalizeShortIdInput, resolveShortIdReadOnly } from './short-id.ts';
|
|
5
5
|
import { parseTaskFrontmatter } from './frontmatter.ts';
|
|
6
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
|
|
6
7
|
|
|
7
8
|
const TASK_ID_RE = /^TASK-\d{8}-\d{6}$/;
|
|
8
9
|
// Flat-structured workspace dirs that hold tasks under `{dir}/{taskId}/task.md`.
|
|
9
10
|
// Note: `archive` uses a three-level YYYY/MM/DD layout and is handled separately.
|
|
10
11
|
const FLAT_WORKSPACE_DIRS = ['active', 'blocked', 'completed'] as const;
|
|
11
12
|
|
|
13
|
+
function taskRoot(repoRoot: string): string { return resolveProjectTaskWorkspaceRoot(repoRoot); }
|
|
14
|
+
|
|
12
15
|
type ResolveRefResult =
|
|
13
16
|
| {
|
|
14
17
|
ok: true;
|
|
@@ -80,12 +83,12 @@ function listSortedNumeric(dir: string, width: number): string[] {
|
|
|
80
83
|
.reverse();
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
function findInArchive(
|
|
84
|
-
// archive-tasks stores local material at
|
|
86
|
+
function findInArchive(workspaceRoot: string, taskId: string): string | null {
|
|
87
|
+
// archive-tasks stores local material at the project task workspace archive/YYYY/MM/DD/{taskId}/local/task.md
|
|
85
88
|
// where YYYY/MM/DD comes from completed_at (or updated_at fallback) — NOT from
|
|
86
89
|
// the task id's creation date. So we cannot derive the path from taskId alone;
|
|
87
90
|
// walk the bounded YYYY/MM/DD tree instead. Newest-first to favor recent archives.
|
|
88
|
-
const archiveDir = path.join(
|
|
91
|
+
const archiveDir = path.join(workspaceRoot, 'archive');
|
|
89
92
|
for (const year of listSortedNumeric(archiveDir, 4)) {
|
|
90
93
|
const yearDir = path.join(archiveDir, year);
|
|
91
94
|
for (const month of listSortedNumeric(yearDir, 2)) {
|
|
@@ -100,14 +103,14 @@ function findInArchive(repoRoot: string, taskId: string): string | null {
|
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
function findTaskMd(
|
|
103
|
-
|
|
106
|
+
workspaceRoot: string,
|
|
104
107
|
taskId: string
|
|
105
108
|
): { taskMdPath: string; state: TaskWorkspaceState } | null {
|
|
106
109
|
for (const sub of FLAT_WORKSPACE_DIRS) {
|
|
107
|
-
const candidate = path.join(
|
|
110
|
+
const candidate = path.join(workspaceRoot, sub, taskId, 'task.md');
|
|
108
111
|
if (fs.existsSync(candidate)) return { taskMdPath: candidate, state: sub };
|
|
109
112
|
}
|
|
110
|
-
const archived = findInArchive(
|
|
113
|
+
const archived = findInArchive(workspaceRoot, taskId);
|
|
111
114
|
return archived ? { taskMdPath: archived, state: 'archive' } : null;
|
|
112
115
|
}
|
|
113
116
|
|
|
@@ -119,8 +122,9 @@ function findTaskMd(
|
|
|
119
122
|
*/
|
|
120
123
|
function enumerateTaskDirs(repoRoot: string): { taskId: string; taskDir: string }[] {
|
|
121
124
|
const out: { taskId: string; taskDir: string }[] = [];
|
|
125
|
+
const workspaceRoot = taskRoot(repoRoot);
|
|
122
126
|
for (const sub of FLAT_WORKSPACE_DIRS) {
|
|
123
|
-
const base = path.join(
|
|
127
|
+
const base = path.join(workspaceRoot, sub);
|
|
124
128
|
if (!fs.existsSync(base)) continue;
|
|
125
129
|
for (const entry of fs.readdirSync(base).sort()) {
|
|
126
130
|
if (!TASK_ID_RE.test(entry)) continue;
|
|
@@ -139,6 +143,7 @@ function enumerateTaskDirs(repoRoot: string): { taskId: string; taskDir: string
|
|
|
139
143
|
*/
|
|
140
144
|
function enumerateAllTaskDirs(repoRoot: string): { taskId: string; taskDir: string; state: TaskWorkspaceState }[] {
|
|
141
145
|
const out: { taskId: string; taskDir: string; state: TaskWorkspaceState }[] = [];
|
|
146
|
+
const workspaceRoot = taskRoot(repoRoot);
|
|
142
147
|
const seen = new Map<string, string>();
|
|
143
148
|
const add = (taskId: string, taskDir: string, state: TaskWorkspaceState) => {
|
|
144
149
|
if (!TASK_ID_RE.test(taskId)) return;
|
|
@@ -155,12 +160,12 @@ function enumerateAllTaskDirs(repoRoot: string): { taskId: string; taskDir: stri
|
|
|
155
160
|
};
|
|
156
161
|
|
|
157
162
|
for (const state of FLAT_WORKSPACE_DIRS) {
|
|
158
|
-
const base = path.join(
|
|
163
|
+
const base = path.join(workspaceRoot, state);
|
|
159
164
|
if (!fs.existsSync(base)) continue;
|
|
160
165
|
for (const taskId of fs.readdirSync(base).sort()) add(taskId, path.join(base, taskId), state);
|
|
161
166
|
}
|
|
162
167
|
|
|
163
|
-
const archive = path.join(
|
|
168
|
+
const archive = path.join(workspaceRoot, 'archive');
|
|
164
169
|
for (const year of listSortedNumeric(archive, 4).reverse()) {
|
|
165
170
|
const yearDir = path.join(archive, year);
|
|
166
171
|
for (const month of listSortedNumeric(yearDir, 2).reverse()) {
|
|
@@ -178,8 +183,9 @@ function locateHotTaskDirs(
|
|
|
178
183
|
repoRoot: string,
|
|
179
184
|
taskId: string
|
|
180
185
|
): { taskId: string; taskDir: string; taskMdPath: string; state: Exclude<TaskWorkspaceState, 'archive'> }[] {
|
|
186
|
+
const workspaceRoot = taskRoot(repoRoot);
|
|
181
187
|
return FLAT_WORKSPACE_DIRS.flatMap((state) => {
|
|
182
|
-
const taskDir = path.join(
|
|
188
|
+
const taskDir = path.join(workspaceRoot, state, taskId);
|
|
183
189
|
const taskMdPath = path.join(taskDir, 'task.md');
|
|
184
190
|
return fs.existsSync(taskMdPath) ? [{ taskId, taskDir, taskMdPath, state }] : [];
|
|
185
191
|
});
|
|
@@ -244,7 +250,7 @@ function resolveTaskRef(arg: string, options: ResolveTaskRefOptions = {}): Resol
|
|
|
244
250
|
}
|
|
245
251
|
taskId = shortResult.taskId;
|
|
246
252
|
}
|
|
247
|
-
const located = findTaskMd(repoRoot, taskId);
|
|
253
|
+
const located = findTaskMd(taskRoot(repoRoot), taskId);
|
|
248
254
|
if (!located) {
|
|
249
255
|
return {
|
|
250
256
|
ok: false,
|
|
@@ -300,7 +306,7 @@ function resolveTaskContext(
|
|
|
300
306
|
};
|
|
301
307
|
}
|
|
302
308
|
|
|
303
|
-
const activeDir = path.join(repoRoot, '
|
|
309
|
+
const activeDir = path.join(taskRoot(repoRoot), 'active');
|
|
304
310
|
const matches: { taskId: string; taskDir: string; taskMdPath: string }[] = [];
|
|
305
311
|
if (fs.existsSync(activeDir)) {
|
|
306
312
|
for (const entry of fs.readdirSync(activeDir).sort()) {
|
|
@@ -10,7 +10,6 @@ import { finalizeReviewSummaryContent } from './review-artifacts.ts';
|
|
|
10
10
|
import { inspectDecisionDetailDuplicates } from './decision-details.ts';
|
|
11
11
|
import { resolveTaskRef } from './resolve-ref.ts';
|
|
12
12
|
import { validateLifecycleExecution } from './lifecycle-execution.ts';
|
|
13
|
-
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.ts';
|
|
14
13
|
import type { ResolveTaskRefErrorCode } from './resolve-ref.ts';
|
|
15
14
|
import { getArtifactSchema } from './artifact-schema.ts';
|
|
16
15
|
import { validateQualificationAudit } from './qualification-audit.ts';
|
|
@@ -69,7 +68,6 @@ type ReviewFileSystem = {
|
|
|
69
68
|
type ReviewFinalizationOptions = {
|
|
70
69
|
repoRoot?: string;
|
|
71
70
|
fileSystem?: Partial<ReviewFileSystem>;
|
|
72
|
-
lockAlreadyHeld?: boolean;
|
|
73
71
|
};
|
|
74
72
|
|
|
75
73
|
const STAGES: Record<ReviewStage, { family: 'review-analysis' | 'review-plan' | 'review-code' }> = {
|
|
@@ -123,7 +121,7 @@ function preflightFailed(
|
|
|
123
121
|
}
|
|
124
122
|
|
|
125
123
|
/** Validate the current review draft before any finding-ledger write. */
|
|
126
|
-
function
|
|
124
|
+
function preflightReviewSummary(
|
|
127
125
|
request: ReviewFinalizationRequest,
|
|
128
126
|
options: ReviewFinalizationOptions = {}
|
|
129
127
|
): ReviewPreflightResult {
|
|
@@ -178,30 +176,9 @@ function preflightReviewSummaryUnlocked(
|
|
|
178
176
|
};
|
|
179
177
|
}
|
|
180
178
|
|
|
181
|
-
function preflightReviewSummary(
|
|
182
|
-
request: ReviewFinalizationRequest,
|
|
183
|
-
options: ReviewFinalizationOptions = {}
|
|
184
|
-
): ReviewPreflightResult {
|
|
185
|
-
if (request.dryRun || options.lockAlreadyHeld) return preflightReviewSummaryUnlocked(request, options);
|
|
186
|
-
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
187
|
-
if (!resolved.ok) return preflightReviewSummaryUnlocked(request, options);
|
|
188
|
-
try {
|
|
189
|
-
return withTaskExecutionLock(
|
|
190
|
-
resolved.repoRoot,
|
|
191
|
-
resolved.taskId,
|
|
192
|
-
'task-review.preflight',
|
|
193
|
-
() => preflightReviewSummaryUnlocked(request, { ...options, lockAlreadyHeld: true })
|
|
194
|
-
);
|
|
195
|
-
} catch (error) {
|
|
196
|
-
if (!(error instanceof TaskExecutionLockError)) throw error;
|
|
197
|
-
return preflightFailed(request, 'REVIEW_PROVENANCE_INVALID', `${error.code}: ${error.message}`, resolved.taskId);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
179
|
type ReviewSummaryCandidatePreparation = Readonly<{
|
|
202
180
|
result: ReviewFinalizationResult;
|
|
203
181
|
content: string;
|
|
204
|
-
lockAlreadyHeld?: boolean;
|
|
205
182
|
}>;
|
|
206
183
|
|
|
207
184
|
/** Prepare domain validation, summary bytes and provenance before any publication. */
|
|
@@ -279,7 +256,6 @@ function prepareReviewSummaryCandidate(
|
|
|
279
256
|
operations: transformed.changed ? [{ kind: 'artifact', artifact: request.artifact, operation: 'update' }] : [],
|
|
280
257
|
error: null
|
|
281
258
|
},
|
|
282
|
-
lockAlreadyHeld: options.lockAlreadyHeld
|
|
283
259
|
};
|
|
284
260
|
}
|
|
285
261
|
|
|
@@ -303,7 +279,7 @@ function replaceCurrentArtifactAtomically(file: string, content: string): void {
|
|
|
303
279
|
}
|
|
304
280
|
}
|
|
305
281
|
|
|
306
|
-
function
|
|
282
|
+
function finalizeReviewSummary(
|
|
307
283
|
request: ReviewFinalizationRequest,
|
|
308
284
|
options: ReviewFinalizationOptions = {}
|
|
309
285
|
): ReviewFinalizationResult {
|
|
@@ -340,32 +316,6 @@ function finalizeReviewSummaryUnlocked(
|
|
|
340
316
|
}
|
|
341
317
|
}
|
|
342
318
|
|
|
343
|
-
function finalizeReviewSummary(
|
|
344
|
-
request: ReviewFinalizationRequest,
|
|
345
|
-
options: ReviewFinalizationOptions = {}
|
|
346
|
-
): ReviewFinalizationResult {
|
|
347
|
-
const effectiveOptions = options;
|
|
348
|
-
if (request.dryRun || options.lockAlreadyHeld) return finalizeReviewSummaryUnlocked(request, effectiveOptions);
|
|
349
|
-
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
350
|
-
if (!resolved.ok) return finalizeReviewSummaryUnlocked(request, effectiveOptions);
|
|
351
|
-
try {
|
|
352
|
-
return withTaskExecutionLock(
|
|
353
|
-
resolved.repoRoot,
|
|
354
|
-
resolved.taskId,
|
|
355
|
-
'task-review.finalize-summary',
|
|
356
|
-
() => finalizeReviewSummaryUnlocked(request, { ...effectiveOptions, lockAlreadyHeld: true })
|
|
357
|
-
);
|
|
358
|
-
} catch (error) {
|
|
359
|
-
if (!(error instanceof TaskExecutionLockError)) throw error;
|
|
360
|
-
return failed(
|
|
361
|
-
request,
|
|
362
|
-
'REVIEW_PROVENANCE_INVALID',
|
|
363
|
-
`${error.code}: ${error.message}`,
|
|
364
|
-
resolved.taskId
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
319
|
export { finalizeReviewSummary, preflightReviewSummary, prepareReviewSummaryCandidate, commitReviewSummaryProvenance };
|
|
370
320
|
export type {
|
|
371
321
|
ReviewFinalizationError,
|
|
@@ -45,7 +45,9 @@ export function inspectReviewIdentity(taskDir: string, reportContent: string, re
|
|
|
45
45
|
}
|
|
46
46
|
try {
|
|
47
47
|
const metadata = parseTypedTaskFrontmatter(fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8'));
|
|
48
|
-
const taskRepositoryRoot =
|
|
48
|
+
const taskRepositoryRoot = repositoryRoot
|
|
49
|
+
? fs.realpathSync.native(repositoryRoot)
|
|
50
|
+
: git(taskDir, ['rev-parse', '--show-toplevel']);
|
|
49
51
|
const branch = String(metadata.branch ?? '').trim();
|
|
50
52
|
const gitRoot = branch ? resolveBranchWorktree(taskRepositoryRoot, branch) : taskRepositoryRoot;
|
|
51
53
|
if (!gitRoot) return result('indeterminate', `Task branch '${branch}' is not checked out in a registered worktree`, reviewedHead);
|
package/lib/task/short-id.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { parseTypedTaskFrontmatter } from './frontmatter.ts';
|
|
4
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
|
|
4
5
|
|
|
5
6
|
const REGISTRY_NAME = '.short-ids.json';
|
|
6
7
|
const LOCK_NAME = '.short-ids.json.lock';
|
|
@@ -85,7 +86,7 @@ function resolveShortIdReadOnly(
|
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
const key = normalized.value;
|
|
88
|
-
const registryPath = path.join(repoRoot, '
|
|
89
|
+
const registryPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', REGISTRY_NAME);
|
|
89
90
|
if (!fs.existsSync(registryPath)) {
|
|
90
91
|
return shortIdFailure(
|
|
91
92
|
'SHORT_ID_REGISTRY_NOT_FOUND',
|
|
@@ -164,8 +165,9 @@ function resolveShortIdReadOnly(
|
|
|
164
165
|
: `short id '${key}' not found in task short-id registry.`;
|
|
165
166
|
return shortIdFailure('SHORT_ID_NOT_FOUND', message);
|
|
166
167
|
}
|
|
167
|
-
const
|
|
168
|
-
const
|
|
168
|
+
const workspaceRoot = resolveProjectTaskWorkspaceRoot(repoRoot);
|
|
169
|
+
const activeTask = path.join(workspaceRoot, 'active', taskId, 'task.md');
|
|
170
|
+
const completedTask = path.join(workspaceRoot, 'completed', taskId, 'task.md');
|
|
169
171
|
let isValidCompletedTask = false;
|
|
170
172
|
try {
|
|
171
173
|
const task = parseTypedTaskFrontmatter(fs.readFileSync(completedTask, 'utf8'));
|
|
@@ -300,7 +302,7 @@ function mutateShortIdRegistry(
|
|
|
300
302
|
taskId: string,
|
|
301
303
|
requested: ShortIdMutationEffect
|
|
302
304
|
): ShortIdMutationResult {
|
|
303
|
-
const activeDir = path.join(repoRoot, '
|
|
305
|
+
const activeDir = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active');
|
|
304
306
|
return mutateShortIdRegistryAt(activeDir, configuredShortIdLength(repoRoot), taskId, requested);
|
|
305
307
|
}
|
|
306
308
|
|
|
@@ -369,7 +371,7 @@ function mutateShortIdRegistryAt(
|
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
function releaseStaleShortIdRegistry(repoRoot: string, taskId: string): ShortIdMutationResult {
|
|
372
|
-
const activeDir = path.join(repoRoot, '
|
|
374
|
+
const activeDir = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active');
|
|
373
375
|
return mutateShortIdRegistryAt(
|
|
374
376
|
activeDir,
|
|
375
377
|
configuredShortIdLength(repoRoot),
|
|
@@ -433,7 +435,7 @@ function executeShortIdCommand(request: ShortIdCommandRequest): ShortIdCommandRe
|
|
|
433
435
|
}
|
|
434
436
|
|
|
435
437
|
function readRegistry(repoRoot: string): RegistrySchema | null {
|
|
436
|
-
const registryPath = path.join(repoRoot, '
|
|
438
|
+
const registryPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', REGISTRY_NAME);
|
|
437
439
|
if (!fs.existsSync(registryPath)) return null;
|
|
438
440
|
try {
|
|
439
441
|
const raw = fs.readFileSync(registryPath, 'utf8');
|
|
@@ -446,7 +448,7 @@ function readRegistry(repoRoot: string): RegistrySchema | null {
|
|
|
446
448
|
}
|
|
447
449
|
|
|
448
450
|
function readBranchFromTaskMd(repoRoot: string, taskId: string): string | null {
|
|
449
|
-
const taskMdPath = path.join(repoRoot, '
|
|
451
|
+
const taskMdPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', taskId, 'task.md');
|
|
450
452
|
if (!fs.existsSync(taskMdPath)) return null;
|
|
451
453
|
const content = fs.readFileSync(taskMdPath, 'utf8');
|
|
452
454
|
const m = content.match(/^branch:\s*(.+)$/m);
|
|
@@ -468,7 +470,7 @@ function inspectShortIdRegistry(
|
|
|
468
470
|
repoRoot: string,
|
|
469
471
|
shortIdLength = configuredShortIdLength(repoRoot)
|
|
470
472
|
): ShortIdRegistryInspection {
|
|
471
|
-
const registryPath = path.join(repoRoot, '
|
|
473
|
+
const registryPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', REGISTRY_NAME);
|
|
472
474
|
if (!fs.existsSync(registryPath)) {
|
|
473
475
|
return {
|
|
474
476
|
status: 'missing',
|