@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
|
@@ -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)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { parseTypedTaskFrontmatter } from './frontmatter.js';
|
|
4
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.js';
|
|
4
5
|
const REGISTRY_NAME = '.short-ids.json';
|
|
5
6
|
const LOCK_NAME = '.short-ids.json.lock';
|
|
6
7
|
function normalizeShortIdInput(input, opts) {
|
|
@@ -42,7 +43,7 @@ function resolveShortIdReadOnly(input, repoRoot, opts) {
|
|
|
42
43
|
return shortIdFailure('SHORT_ID_NOT_FOUND', `short id '${input}' not found in active task registry`);
|
|
43
44
|
}
|
|
44
45
|
const key = normalized.value;
|
|
45
|
-
const registryPath = path.join(repoRoot, '
|
|
46
|
+
const registryPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', REGISTRY_NAME);
|
|
46
47
|
if (!fs.existsSync(registryPath)) {
|
|
47
48
|
return shortIdFailure('SHORT_ID_REGISTRY_NOT_FOUND', `short id '${key}' not found; active task registry is empty.`);
|
|
48
49
|
}
|
|
@@ -95,8 +96,9 @@ function resolveShortIdReadOnly(input, repoRoot, opts) {
|
|
|
95
96
|
: `short id '${key}' not found in task short-id registry.`;
|
|
96
97
|
return shortIdFailure('SHORT_ID_NOT_FOUND', message);
|
|
97
98
|
}
|
|
98
|
-
const
|
|
99
|
-
const
|
|
99
|
+
const workspaceRoot = resolveProjectTaskWorkspaceRoot(repoRoot);
|
|
100
|
+
const activeTask = path.join(workspaceRoot, 'active', taskId, 'task.md');
|
|
101
|
+
const completedTask = path.join(workspaceRoot, 'completed', taskId, 'task.md');
|
|
100
102
|
let isValidCompletedTask = false;
|
|
101
103
|
try {
|
|
102
104
|
const task = parseTypedTaskFrontmatter(fs.readFileSync(completedTask, 'utf8'));
|
|
@@ -210,7 +212,7 @@ function writeRegistry(registryPath, registry) {
|
|
|
210
212
|
}
|
|
211
213
|
}
|
|
212
214
|
function mutateShortIdRegistry(repoRoot, taskId, requested) {
|
|
213
|
-
const activeDir = path.join(repoRoot, '
|
|
215
|
+
const activeDir = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active');
|
|
214
216
|
return mutateShortIdRegistryAt(activeDir, configuredShortIdLength(repoRoot), taskId, requested);
|
|
215
217
|
}
|
|
216
218
|
function mutateShortIdRegistryAt(activeDir, width, taskId, requested, onlyReleaseWhenInactive = false, pruneOrphans = true) {
|
|
@@ -267,7 +269,7 @@ function mutateShortIdRegistryAt(activeDir, width, taskId, requested, onlyReleas
|
|
|
267
269
|
});
|
|
268
270
|
}
|
|
269
271
|
function releaseStaleShortIdRegistry(repoRoot, taskId) {
|
|
270
|
-
const activeDir = path.join(repoRoot, '
|
|
272
|
+
const activeDir = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active');
|
|
271
273
|
return mutateShortIdRegistryAt(activeDir, configuredShortIdLength(repoRoot), taskId, 'release', true, false);
|
|
272
274
|
}
|
|
273
275
|
function executeShortIdCommand(request) {
|
|
@@ -327,7 +329,7 @@ function executeShortIdCommand(request) {
|
|
|
327
329
|
}
|
|
328
330
|
}
|
|
329
331
|
function readRegistry(repoRoot) {
|
|
330
|
-
const registryPath = path.join(repoRoot, '
|
|
332
|
+
const registryPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', REGISTRY_NAME);
|
|
331
333
|
if (!fs.existsSync(registryPath))
|
|
332
334
|
return null;
|
|
333
335
|
try {
|
|
@@ -342,7 +344,7 @@ function readRegistry(repoRoot) {
|
|
|
342
344
|
}
|
|
343
345
|
}
|
|
344
346
|
function readBranchFromTaskMd(repoRoot, taskId) {
|
|
345
|
-
const taskMdPath = path.join(repoRoot, '
|
|
347
|
+
const taskMdPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', taskId, 'task.md');
|
|
346
348
|
if (!fs.existsSync(taskMdPath))
|
|
347
349
|
return null;
|
|
348
350
|
const content = fs.readFileSync(taskMdPath, 'utf8');
|
|
@@ -362,7 +364,7 @@ function loadShortIdByTaskId(repoRoot) {
|
|
|
362
364
|
return map;
|
|
363
365
|
}
|
|
364
366
|
function inspectShortIdRegistry(repoRoot, shortIdLength = configuredShortIdLength(repoRoot)) {
|
|
365
|
-
const registryPath = path.join(repoRoot, '
|
|
367
|
+
const registryPath = path.join(resolveProjectTaskWorkspaceRoot(repoRoot), 'active', REGISTRY_NAME);
|
|
366
368
|
if (!fs.existsSync(registryPath)) {
|
|
367
369
|
return {
|
|
368
370
|
status: 'missing',
|
|
@@ -54,9 +54,7 @@ const DEFAULT_REQUIRED_FIELDS = [
|
|
|
54
54
|
"assigned_to"
|
|
55
55
|
];
|
|
56
56
|
const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
|
|
57
|
-
//
|
|
58
|
-
// "latest action" / freshness computation so a step's in-flight marker never
|
|
59
|
-
// satisfies a skill's expected_action_pattern; the matching done entry does.
|
|
57
|
+
// Started rows do not represent completed lifecycle actions.
|
|
60
58
|
const ACTIVITY_LOG_STARTED_RE = /\s*\[started\]\s*$/;
|
|
61
59
|
const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
62
60
|
// Review disagreement ledger (see .agents/rules/review-handshake.md).
|
|
@@ -322,15 +320,9 @@ function checkTaskMeta({ taskDir, config, repositoryRoot, skillName, artifactFil
|
|
|
322
320
|
if (expectedStep && metadata.current_step !== expectedStep) {
|
|
323
321
|
let validLifecycleArtifact = false;
|
|
324
322
|
if (currentTask) {
|
|
325
|
-
const activityConfig = loadVerificationConfig(repositoryRoot, skillName).checks?.["activity-log"];
|
|
326
323
|
const { section, invalidEntries } = inspectActivityLog(task.content);
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
for (const entry of section.entries) {
|
|
330
|
-
if (!ACTIVITY_LOG_STARTED_RE.test(entry.step))
|
|
331
|
-
latestAction = entry.step;
|
|
332
|
-
}
|
|
333
|
-
validLifecycleArtifact = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, activityConfig, task, section.entries, latestAction)?.status === "pass";
|
|
324
|
+
if (section && invalidEntries.length === 0) {
|
|
325
|
+
validLifecycleArtifact = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task, section.entries)?.status === "pass";
|
|
334
326
|
}
|
|
335
327
|
}
|
|
336
328
|
if (!validLifecycleArtifact) {
|
|
@@ -634,14 +626,14 @@ function checkImplementationInput({ taskDir, artifactFile }) {
|
|
|
634
626
|
return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
|
|
635
627
|
}
|
|
636
628
|
const ARTIFACT_ACTIVITY_STAGES = {
|
|
637
|
-
"analyze-task": { family: "analysis", event: "analyze.completed" },
|
|
638
|
-
"plan-task": { family: "plan", event: "plan.completed" },
|
|
639
|
-
"review-analysis": { family: "review-analysis", event: "review-analysis.completed" },
|
|
640
|
-
"review-plan": { family: "review-plan", event: "review-plan.completed" },
|
|
641
|
-
"code-task": { family: "code", event: "code.completed" },
|
|
642
|
-
"review-code": { family: "review-code", event: "review-code.completed" }
|
|
629
|
+
"analyze-task": { family: "analysis", event: "analyze.completed", action: "Analyze Task" },
|
|
630
|
+
"plan-task": { family: "plan", event: "plan.completed", action: "Plan Task" },
|
|
631
|
+
"review-analysis": { family: "review-analysis", event: "review-analysis.completed", action: "Review Analysis" },
|
|
632
|
+
"review-plan": { family: "review-plan", event: "review-plan.completed", action: "Review Plan" },
|
|
633
|
+
"code-task": { family: "code", event: "code.completed", action: "Code Task" },
|
|
634
|
+
"review-code": { family: "review-code", event: "review-code.completed", action: "Review Code" }
|
|
643
635
|
};
|
|
644
|
-
function checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName,
|
|
636
|
+
function checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task, entries) {
|
|
645
637
|
const stage = ARTIFACT_ACTIVITY_STAGES[skillName];
|
|
646
638
|
if (!stage)
|
|
647
639
|
return null;
|
|
@@ -680,26 +672,18 @@ function checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, con
|
|
|
680
672
|
return failResult("activity-log", `Input '${input.name}' changed or is no longer current; rerun ${skillName} to refresh '${output}'`);
|
|
681
673
|
}
|
|
682
674
|
}
|
|
683
|
-
const
|
|
675
|
+
const roundActionPattern = new RegExp(`^${stage.action} \\(Round ${identity.round}(?:, [^)]+)?\\)$`);
|
|
684
676
|
const roundAction = entries.find((entry) => {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
return false;
|
|
689
|
-
expectedAction.lastIndex = 0;
|
|
690
|
-
const actionRound = /\(Round (\d+)/.exec(entry.step)?.[1];
|
|
691
|
-
return actionRound === String(identity.round) && entry.note.includes(`→ ${output}`);
|
|
677
|
+
return !ACTIVITY_LOG_STARTED_RE.test(entry.step)
|
|
678
|
+
&& roundActionPattern.test(entry.step)
|
|
679
|
+
&& entry.note.includes(`→ ${output}`);
|
|
692
680
|
});
|
|
693
681
|
if (!roundAction) {
|
|
694
682
|
return failResult("activity-log", `No completed Activity Log row records '${output}' for ${skillName} Round ${identity.round}`);
|
|
695
683
|
}
|
|
696
|
-
if (skillName === "plan-task" && /^(?:Human Decision|Decision)\b/.test(latestAction)
|
|
697
|
-
&& expectedAction.test(latestAction)) {
|
|
698
|
-
return passResult("activity-log", `Plan completion '${output}' is current; latest action '${latestAction}' is a human decision`);
|
|
699
|
-
}
|
|
700
684
|
return passResult("activity-log", `Current ${stage.family} completion '${output}' is valid for Round ${identity.round}`);
|
|
701
685
|
}
|
|
702
|
-
function checkActivityLog({ taskDir,
|
|
686
|
+
function checkActivityLog({ taskDir, skillName, artifactFile }) {
|
|
703
687
|
const task = loadTask(taskDir);
|
|
704
688
|
if (!task.ok) {
|
|
705
689
|
return failResult("activity-log", task.message);
|
|
@@ -712,37 +696,14 @@ function checkActivityLog({ taskDir, config, skillName, artifactFile }) {
|
|
|
712
696
|
const entries = section.entries;
|
|
713
697
|
if (entries.length === 0)
|
|
714
698
|
return failResult("activity-log", "Activity Log has no entries");
|
|
715
|
-
let latestAction = "";
|
|
716
|
-
let latestTimestamp = "";
|
|
717
|
-
const doneActions = [];
|
|
718
699
|
for (const entry of entries) {
|
|
719
700
|
if (!entry.note.trim())
|
|
720
701
|
return failResult("activity-log", "Activity Log entry note is required");
|
|
721
|
-
const { time: timestamp, step: action } = entry;
|
|
722
|
-
// A `[started]` marker is not a terminal action: keep latestAction/latestTimestamp
|
|
723
|
-
// on the most recent done entry so expected_action_pattern sees it.
|
|
724
|
-
if (!ACTIVITY_LOG_STARTED_RE.test(action)) {
|
|
725
|
-
latestTimestamp = timestamp;
|
|
726
|
-
latestAction = action;
|
|
727
|
-
doneActions.push(action);
|
|
728
|
-
}
|
|
729
702
|
}
|
|
730
|
-
const artifactLifecycleResult = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName,
|
|
703
|
+
const artifactLifecycleResult = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task, entries);
|
|
731
704
|
if (artifactLifecycleResult)
|
|
732
705
|
return artifactLifecycleResult;
|
|
733
|
-
|
|
734
|
-
const expected = new RegExp(config.expected_action_pattern);
|
|
735
|
-
let index = doneActions.length - 1;
|
|
736
|
-
while (index >= 0 && doneActions[index] === 'Commit' && !expected.test(doneActions[index]))
|
|
737
|
-
index -= 1;
|
|
738
|
-
if (index >= 0 && expected.test(doneActions[index])) {
|
|
739
|
-
latestAction = doneActions[index];
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
if (config.expected_action_pattern && !new RegExp(config.expected_action_pattern).test(latestAction)) {
|
|
743
|
-
return failResult("activity-log", `Latest action '${latestAction}' does not match '${config.expected_action_pattern}'`);
|
|
744
|
-
}
|
|
745
|
-
return passResult("activity-log", `Latest entry '${latestAction}' at ${latestTimestamp}`);
|
|
706
|
+
return passResult("activity-log", "Activity Log is valid");
|
|
746
707
|
}
|
|
747
708
|
function checkCompletionChecklist({ taskDir, config }) {
|
|
748
709
|
const task = loadTask(taskDir);
|
|
@@ -932,10 +893,10 @@ async function checkPostReviewCommit({ taskDir, config, repositoryRoot }) {
|
|
|
932
893
|
}
|
|
933
894
|
let gitRoot;
|
|
934
895
|
try {
|
|
935
|
-
gitRoot = execFileSync("git", ["-C",
|
|
896
|
+
gitRoot = execFileSync("git", ["-C", repositoryRoot, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
|
|
936
897
|
}
|
|
937
898
|
catch {
|
|
938
|
-
return blockedResult("post-review-commit", "git unavailable or
|
|
899
|
+
return blockedResult("post-review-commit", "git unavailable or repository root is not inside a git repository");
|
|
939
900
|
}
|
|
940
901
|
const task = loadTask(taskDir);
|
|
941
902
|
if (!task.ok)
|