@fitlab-ai/agent-infra 0.9.13 → 0.9.14
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 +26 -9
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +42 -21
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/internal/agent-client.js +5 -2
- package/dist/lib/internal/cli-route-inventory.js +152 -0
- package/dist/lib/internal/codex-lifecycle.js +9 -6
- package/dist/lib/internal/codex-sandbox-controller.js +8 -2
- package/dist/lib/internal/git-workflow.js +10 -6
- package/dist/lib/internal/platform-checks.js +16 -4
- package/dist/lib/internal/platform-comment.js +16 -4
- package/dist/lib/internal/platform-context.js +4 -1
- package/dist/lib/internal/platform-issue.js +12 -4
- package/dist/lib/internal/platform-metadata.js +88 -0
- package/dist/lib/internal/platform-pr-review.js +16 -3
- package/dist/lib/internal/platform-pr.js +24 -10
- package/dist/lib/internal/platform-release-notes.js +6 -3
- package/dist/lib/internal/platform-security.js +93 -0
- package/dist/lib/internal/pr-review-grade.js +14 -3
- package/dist/lib/internal/release-workflow.js +19 -5
- package/dist/lib/internal/sandbox-control.js +22 -5
- package/dist/lib/internal/task-activity.js +13 -4
- package/dist/lib/internal/task-artifact.js +186 -27
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +48 -15
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +4 -1
- package/dist/lib/internal/task-finalization.js +4 -1
- package/dist/lib/internal/task-invalidation.js +4 -1
- package/dist/lib/internal/task-ledger.js +12 -1
- package/dist/lib/internal/task-lifecycle.js +4 -1
- package/dist/lib/internal/task-operation-registry.js +421 -0
- package/dist/lib/internal/task-orchestration.js +12 -0
- package/dist/lib/internal/task-override.js +10 -3
- package/dist/lib/internal/task-qualification.js +90 -0
- package/dist/lib/internal/task-review.js +4 -1
- package/dist/lib/internal/task-short-id.js +11 -1
- package/dist/lib/internal/task-snapshot.js +4 -1
- package/dist/lib/internal/task-validate.js +7 -2
- package/dist/lib/internal/task-verify.js +5 -1
- package/dist/lib/internal/task-warning.js +8 -1
- package/dist/lib/platform/comment-safety.js +226 -0
- package/dist/lib/platform/github-provider.js +233 -6
- package/dist/lib/platform/issue-comments.js +146 -34
- package/dist/lib/platform/pr-change-report.js +6 -12
- package/dist/lib/platform/pr-summary.js +28 -7
- package/dist/lib/platform/provider-contract.d.ts +67 -1
- package/dist/lib/platform/provider-contract.js +6 -2
- package/dist/lib/platform/provider-validation.js +76 -3
- package/dist/lib/platform/pull-requests.js +115 -170
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/verification-sync.js +33 -26
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/run/index.js +5 -0
- package/dist/lib/sandbox/commands/control-status.js +22 -0
- package/dist/lib/sandbox/commands/create.js +32 -6
- package/dist/lib/sandbox/commands/ls.js +5 -0
- package/dist/lib/sandbox/commands/rm.js +827 -120
- package/dist/lib/sandbox/commands/show.js +16 -0
- package/dist/lib/sandbox/control/client.js +83 -9
- package/dist/lib/sandbox/control/completed-reentry.js +85 -0
- package/dist/lib/sandbox/control/container-identity.js +28 -31
- package/dist/lib/sandbox/control/executor.js +149 -14
- package/dist/lib/sandbox/control/lifecycle.js +621 -127
- package/dist/lib/sandbox/control/native-file-lock.js +177 -0
- package/dist/lib/sandbox/control/server.js +305 -35
- package/dist/lib/sandbox/control/state.js +5 -3
- package/dist/lib/sandbox/control/task-view.js +183 -0
- package/dist/lib/sandbox/engines/authority.js +289 -0
- package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
- package/dist/lib/sandbox/index.js +5 -0
- package/dist/lib/sandbox/recovery.js +21 -1
- package/dist/lib/sandbox/workspace-view.js +2 -1
- package/dist/lib/sandbox/worktree-safety.js +4 -1
- package/dist/lib/server/index.js +8 -0
- package/dist/lib/task/artifact-lifecycle.js +42 -13
- package/dist/lib/task/artifact-operations.js +520 -0
- package/dist/lib/task/artifact-repair-intent.js +59 -0
- package/dist/lib/task/artifact-schema.js +135 -0
- package/dist/lib/task/capabilities.js +72 -1
- package/dist/lib/task/control-authority.js +4 -0
- package/dist/lib/task/create-service.js +103 -4
- package/dist/lib/task/create.js +25 -0
- package/dist/lib/task/events.js +186 -67
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/local-artifact-finalization.js +75 -150
- package/dist/lib/task/orchestration.js +192 -52
- package/dist/lib/task/qualification-audit.js +490 -0
- package/dist/lib/task/qualification-confirmation.js +109 -0
- package/dist/lib/task/qualification-intents.js +148 -0
- package/dist/lib/task/review-artifacts.js +22 -23
- package/dist/lib/task/review-finalization.js +121 -4
- package/dist/lib/task/sections.js +6 -4
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +54 -4
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/internal/agent-client.ts +4 -2
- package/lib/internal/cli-route-inventory.ts +140 -0
- package/lib/internal/codex-lifecycle.ts +8 -6
- package/lib/internal/codex-sandbox-controller.ts +7 -2
- package/lib/internal/git-workflow.ts +9 -6
- package/lib/internal/platform-checks.ts +12 -4
- package/lib/internal/platform-comment.ts +12 -4
- package/lib/internal/platform-context.ts +3 -1
- package/lib/internal/platform-issue.ts +11 -4
- package/lib/internal/platform-metadata.ts +70 -0
- package/lib/internal/platform-pr-review.ts +14 -3
- package/lib/internal/platform-pr.ts +23 -10
- package/lib/internal/platform-release-notes.ts +5 -3
- package/lib/internal/platform-security.ts +83 -0
- package/lib/internal/pr-review-grade.ts +10 -3
- package/lib/internal/release-workflow.ts +17 -5
- package/lib/internal/sandbox-control.ts +19 -5
- package/lib/internal/task-activity.ts +12 -4
- package/lib/internal/task-artifact.ts +164 -25
- package/lib/internal/task-context.ts +3 -1
- package/lib/internal/task-create.ts +76 -15
- package/lib/internal/task-delivery.ts +3 -1
- package/lib/internal/task-event.ts +3 -1
- package/lib/internal/task-finalization.ts +3 -1
- package/lib/internal/task-invalidation.ts +3 -1
- package/lib/internal/task-ledger.ts +11 -1
- package/lib/internal/task-lifecycle.ts +3 -1
- package/lib/internal/task-operation-registry.ts +482 -0
- package/lib/internal/task-orchestration.ts +12 -0
- package/lib/internal/task-override.ts +9 -3
- package/lib/internal/task-qualification.ts +61 -0
- package/lib/internal/task-review.ts +3 -1
- package/lib/internal/task-short-id.ts +10 -1
- package/lib/internal/task-snapshot.ts +3 -1
- package/lib/internal/task-validate.ts +6 -2
- package/lib/internal/task-verify.ts +4 -1
- package/lib/internal/task-warning.ts +7 -1
- package/lib/platform/comment-safety.ts +250 -0
- package/lib/platform/github-provider.ts +229 -7
- package/lib/platform/issue-comments.ts +160 -35
- package/lib/platform/pr-change-report.ts +6 -12
- package/lib/platform/pr-summary.ts +27 -6
- package/lib/platform/provider-contract.ts +78 -3
- package/lib/platform/provider-validation.ts +85 -3
- package/lib/platform/pull-requests.ts +126 -178
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/verification-sync.ts +32 -28
- package/lib/process-data/index.ts +7 -0
- package/lib/run/index.ts +5 -0
- package/lib/sandbox/commands/control-status.ts +26 -0
- package/lib/sandbox/commands/create.ts +46 -6
- package/lib/sandbox/commands/ls.ts +7 -0
- package/lib/sandbox/commands/rm.ts +1000 -87
- package/lib/sandbox/commands/show.ts +16 -0
- package/lib/sandbox/control/client.ts +103 -9
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +177 -12
- package/lib/sandbox/control/lifecycle.ts +629 -17
- package/lib/sandbox/control/native-file-lock.ts +209 -0
- package/lib/sandbox/control/protocol.ts +5 -2
- package/lib/sandbox/control/server.ts +319 -37
- package/lib/sandbox/control/state.ts +6 -3
- package/lib/sandbox/control/task-view.ts +240 -0
- package/lib/sandbox/engines/authority.ts +365 -0
- package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
- package/lib/sandbox/index.ts +7 -0
- package/lib/sandbox/recovery.ts +21 -1
- package/lib/sandbox/workspace-view.ts +9 -3
- package/lib/sandbox/worktree-safety.ts +4 -1
- package/lib/server/index.ts +10 -0
- package/lib/task/artifact-lifecycle.ts +38 -16
- package/lib/task/artifact-operations.ts +626 -0
- package/lib/task/artifact-repair-intent.ts +71 -0
- package/lib/task/artifact-schema.ts +192 -0
- package/lib/task/capabilities.ts +70 -1
- package/lib/task/control-authority.ts +11 -1
- package/lib/task/create-service.ts +131 -6
- package/lib/task/create.ts +27 -0
- package/lib/task/events.ts +161 -65
- package/lib/task/index.ts +16 -3
- package/lib/task/local-artifact-finalization.ts +87 -218
- package/lib/task/orchestration.ts +172 -49
- package/lib/task/qualification-audit.ts +599 -0
- package/lib/task/qualification-confirmation.ts +117 -0
- package/lib/task/qualification-intents.ts +150 -0
- package/lib/task/review-artifacts.ts +21 -22
- package/lib/task/review-finalization.ts +133 -4
- package/lib/task/sections.ts +6 -4
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +55 -4
- package/package.json +6 -1
- package/templates/.agents/rules/README.en.md +2 -0
- package/templates/.agents/rules/README.zh-CN.md +2 -0
- package/templates/.agents/rules/decision-qualification.en.md +22 -0
- package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
- package/templates/.agents/rules/evidence-reporting.en.md +28 -0
- package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
- package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
- package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
- package/templates/.agents/rules/security-alerts.en.md +8 -8
- package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
- package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
- package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
- package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
- package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/complete-task/SKILL.en.md +9 -22
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +9 -22
- package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
- 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-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
- package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
- package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
- package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
- package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
- package/templates/.agents/skills/test/SKILL.en.md +13 -2
- package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
- package/templates/.agents/templates/task.en.md +6 -0
- package/templates/.agents/templates/task.zh-CN.md +6 -0
- package/templates/.agents/scripts/security-alerts.github.sh +0 -151
- package/templates/.agents/scripts/security-alerts.sh +0 -31
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
4
4
|
|
|
5
5
|
import { parseTypedTaskFrontmatter } from './frontmatter.ts';
|
|
6
6
|
import { validateCurrentTaskContract } from './current-contract.ts';
|
|
@@ -154,6 +154,7 @@ type OrchestrationCompletionPlanResult = Readonly<{
|
|
|
154
154
|
type OrchestrationOptions = {
|
|
155
155
|
repoRoot?: string;
|
|
156
156
|
gitWorktreeRoot?: string;
|
|
157
|
+
diagnosticLog?: OrchestrationDiagnosticLogger;
|
|
157
158
|
id?: () => string;
|
|
158
159
|
now?: () => string;
|
|
159
160
|
maxSteps?: number;
|
|
@@ -178,6 +179,10 @@ type OrchestrationOptions = {
|
|
|
178
179
|
hasActiveLifecycleEvidence?: (receipt: DelegationReceipt) => boolean;
|
|
179
180
|
};
|
|
180
181
|
|
|
182
|
+
export type OrchestrationDiagnosticValue = string | number | boolean | null;
|
|
183
|
+
export type OrchestrationDiagnosticFields = Readonly<Record<string, OrchestrationDiagnosticValue>>;
|
|
184
|
+
export type OrchestrationDiagnosticLogger = (event: string, fields: OrchestrationDiagnosticFields) => void;
|
|
185
|
+
|
|
181
186
|
function supportsLifecycleDelegation(client: AgentClientId): boolean {
|
|
182
187
|
return getAgentClientCapability(client, 'subagents').level !== 'unsupported'
|
|
183
188
|
&& getAgentClientCapability(client, 'orchestration').level !== 'unsupported'
|
|
@@ -194,11 +199,13 @@ const ORCHESTRATION_STATE_INVALID_MESSAGE = 'orchestration.json does not match t
|
|
|
194
199
|
class OrchestrationStateError extends Error {
|
|
195
200
|
readonly code = 'ORCHESTRATION_STATE_INVALID';
|
|
196
201
|
readonly taskId: string | null;
|
|
202
|
+
readonly reasonCodes: readonly string[];
|
|
197
203
|
|
|
198
|
-
constructor(taskId: string | null = null) {
|
|
204
|
+
constructor(taskId: string | null = null, reasonCodes: readonly string[] = []) {
|
|
199
205
|
super(ORCHESTRATION_STATE_INVALID_MESSAGE);
|
|
200
206
|
this.name = 'OrchestrationStateError';
|
|
201
207
|
this.taskId = taskId;
|
|
208
|
+
this.reasonCodes = Object.freeze([...reasonCodes]);
|
|
202
209
|
}
|
|
203
210
|
}
|
|
204
211
|
|
|
@@ -288,46 +295,128 @@ const ORCHESTRATION_RUN_KEYS = [
|
|
|
288
295
|
'pause', 'commitAuthorization', 'completionEvidence', 'createdAt', 'updatedAt'
|
|
289
296
|
] as const;
|
|
290
297
|
|
|
291
|
-
function
|
|
292
|
-
if (!hasExactKeys(value, ORCHESTRATION_RUN_KEYS)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
298
|
+
function orchestrationStateReasonCodes(value: unknown, expectedTaskId?: string): string[] {
|
|
299
|
+
if (!hasExactKeys(value, ORCHESTRATION_RUN_KEYS)) return ['top-level-keys'];
|
|
300
|
+
const record = value;
|
|
301
|
+
const reasons: string[] = [];
|
|
302
|
+
if (!exactText(record.taskId)) reasons.push('taskId');
|
|
303
|
+
else if (expectedTaskId !== undefined && record.taskId !== expectedTaskId) reasons.push('taskId-mismatch');
|
|
304
|
+
if (!exactText(record.runId)) reasons.push('runId');
|
|
305
|
+
if (!['running', 'paused', 'completed'].includes(record.status as string)) reasons.push('status');
|
|
306
|
+
if (!(record.nextStage === null || ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code', 'commit'].includes(record.nextStage as string))) {
|
|
307
|
+
reasons.push('nextStage');
|
|
308
|
+
}
|
|
309
|
+
if (!Number.isSafeInteger(record.stepCount) || (record.stepCount as number) < 0) reasons.push('stepCount');
|
|
310
|
+
if (!Number.isSafeInteger(record.maxSteps) || (record.maxSteps as number) < 1) reasons.push('maxSteps');
|
|
311
|
+
if (!isModelPolicy(record.modelPolicy)) reasons.push('modelPolicy');
|
|
312
|
+
if (!isModelPolicySource(record.modelPolicySource)) reasons.push('modelPolicySource');
|
|
313
|
+
if (!Array.isArray(record.recoveryHistory) || !record.recoveryHistory.every(isRecovery)) reasons.push('recoveryHistory');
|
|
314
|
+
if (typeof record.baseline !== 'string') reasons.push('baseline');
|
|
315
|
+
if (!(record.pendingDelegation === null || isDelegationReceipt(record.pendingDelegation))) reasons.push('pendingDelegation');
|
|
316
|
+
if (!Array.isArray(record.receipts) || !record.receipts.every(isDelegationReceipt)) reasons.push('receipts');
|
|
317
|
+
if (!(record.pause === null || isPause(record.pause))) reasons.push('pause');
|
|
318
|
+
if (!hasExactKeys(record.commitAuthorization, ['issuedAt', 'consumedAt'])) {
|
|
319
|
+
reasons.push('commitAuthorization');
|
|
320
|
+
} else {
|
|
321
|
+
if (!nullableText(record.commitAuthorization.issuedAt)) reasons.push('commitAuthorization.issuedAt');
|
|
322
|
+
if (!nullableText(record.commitAuthorization.consumedAt)) reasons.push('commitAuthorization.consumedAt');
|
|
314
323
|
}
|
|
315
|
-
|
|
316
|
-
if (
|
|
317
|
-
|
|
324
|
+
if (!(record.completionEvidence === null || isCompletionEvidence(record.completionEvidence))) reasons.push('completionEvidence');
|
|
325
|
+
if (!exactText(record.createdAt)) reasons.push('createdAt');
|
|
326
|
+
if (!exactText(record.updatedAt)) reasons.push('updatedAt');
|
|
327
|
+
if (Array.isArray(record.receipts) && record.receipts.every(isDelegationReceipt)
|
|
328
|
+
&& (record.pendingDelegation === null || isDelegationReceipt(record.pendingDelegation))) {
|
|
329
|
+
const receipts = [...record.receipts, ...(record.pendingDelegation ? [record.pendingDelegation] : [])];
|
|
330
|
+
if (receipts.some((receipt) => receipt.taskId !== record.taskId || receipt.runId !== record.runId)) {
|
|
331
|
+
reasons.push('receipt-identity');
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return reasons;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function emitDiagnostic(options: Pick<OrchestrationOptions, 'diagnosticLog'> | undefined, event: string, fields: OrchestrationDiagnosticFields): void {
|
|
338
|
+
try {
|
|
339
|
+
options?.diagnosticLog?.(event, fields);
|
|
340
|
+
} catch {
|
|
341
|
+
// Diagnostics must never change lifecycle behavior.
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function fileObservation(file: string): OrchestrationDiagnosticFields {
|
|
346
|
+
try {
|
|
347
|
+
const stat = fs.lstatSync(file);
|
|
348
|
+
let realpath: string | null = null;
|
|
349
|
+
try { realpath = fs.realpathSync.native(file); } catch { /* retain the lstat observation */ }
|
|
350
|
+
return {
|
|
351
|
+
file,
|
|
352
|
+
exists: true,
|
|
353
|
+
fileType: stat.isFile() ? 'file' : stat.isDirectory() ? 'directory' : 'other',
|
|
354
|
+
symbolicLink: stat.isSymbolicLink(),
|
|
355
|
+
bytes: stat.isFile() ? stat.size : null,
|
|
356
|
+
mtimeMs: stat.mtimeMs,
|
|
357
|
+
device: stat.dev,
|
|
358
|
+
inode: stat.ino,
|
|
359
|
+
realpath
|
|
360
|
+
};
|
|
361
|
+
} catch (error) {
|
|
362
|
+
return {
|
|
363
|
+
file,
|
|
364
|
+
exists: false,
|
|
365
|
+
fileType: null,
|
|
366
|
+
symbolicLink: null,
|
|
367
|
+
bytes: null,
|
|
368
|
+
mtimeMs: null,
|
|
369
|
+
device: null,
|
|
370
|
+
inode: null,
|
|
371
|
+
realpath: null,
|
|
372
|
+
fsError: error instanceof Error && 'code' in error ? String(error.code) : null
|
|
373
|
+
};
|
|
318
374
|
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function parseOrchestrationRun(value: unknown, expectedTaskId?: string): OrchestrationRun {
|
|
378
|
+
const reasonCodes = orchestrationStateReasonCodes(value, expectedTaskId);
|
|
379
|
+
if (reasonCodes.length > 0) throw new OrchestrationStateError(expectedTaskId ?? null, reasonCodes);
|
|
319
380
|
return value as OrchestrationRun;
|
|
320
381
|
}
|
|
321
382
|
|
|
322
|
-
function readRun(taskDir: string): OrchestrationRun | null {
|
|
383
|
+
function readRun(taskDir: string, options: Pick<OrchestrationOptions, 'diagnosticLog'> = {}): OrchestrationRun | null {
|
|
323
384
|
const file = orchestrationPath(taskDir);
|
|
324
|
-
if (!fs.existsSync(file)) return null;
|
|
325
385
|
const taskId = path.basename(taskDir);
|
|
386
|
+
const observed = options.diagnosticLog ? fileObservation(file) : {};
|
|
387
|
+
if (!fs.existsSync(file)) {
|
|
388
|
+
emitDiagnostic(options, 'orchestration-state-missing', { taskId, taskDir, ...observed });
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
emitDiagnostic(options, 'orchestration-state-read-start', { taskId, taskDir, ...observed });
|
|
392
|
+
let rawBytes: number | null = null;
|
|
393
|
+
let rawSha256: string | null = null;
|
|
326
394
|
try {
|
|
327
|
-
|
|
395
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
396
|
+
if (options.diagnosticLog) {
|
|
397
|
+
rawBytes = Buffer.byteLength(raw, 'utf8');
|
|
398
|
+
rawSha256 = createHash('sha256').update(raw, 'utf8').digest('hex');
|
|
399
|
+
}
|
|
400
|
+
const run = parseOrchestrationRun(JSON.parse(raw), taskId);
|
|
401
|
+
emitDiagnostic(options, 'orchestration-state-read-ok', {
|
|
402
|
+
taskId, taskDir, file, rawBytes, rawSha256, status: run.status, runId: run.runId,
|
|
403
|
+
stepCount: run.stepCount, pendingDelegation: run.pendingDelegation !== null
|
|
404
|
+
});
|
|
405
|
+
return run;
|
|
328
406
|
} catch (error) {
|
|
329
|
-
|
|
330
|
-
|
|
407
|
+
const reasonCodes = error instanceof OrchestrationStateError && error.reasonCodes.length > 0
|
|
408
|
+
? error.reasonCodes
|
|
409
|
+
: [error instanceof SyntaxError ? 'json-parse' : 'file-read'];
|
|
410
|
+
emitDiagnostic(options, 'orchestration-state-read-failed', {
|
|
411
|
+
taskId,
|
|
412
|
+
taskDir,
|
|
413
|
+
...observed,
|
|
414
|
+
rawBytes,
|
|
415
|
+
rawSha256,
|
|
416
|
+
reasonCodes: reasonCodes.join(','),
|
|
417
|
+
errorType: error instanceof Error ? error.name : typeof error,
|
|
418
|
+
});
|
|
419
|
+
throw new OrchestrationStateError(taskId, reasonCodes);
|
|
331
420
|
}
|
|
332
421
|
}
|
|
333
422
|
|
|
@@ -417,7 +506,7 @@ function beginOrResumeOrchestration(taskRef: string, options: OrchestrationOptio
|
|
|
417
506
|
}
|
|
418
507
|
let existing: OrchestrationRun | null;
|
|
419
508
|
try {
|
|
420
|
-
existing = readRun(resolved.taskDir);
|
|
509
|
+
existing = readRun(resolved.taskDir, options);
|
|
421
510
|
} catch (error) {
|
|
422
511
|
return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
423
512
|
}
|
|
@@ -616,7 +705,7 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
616
705
|
}
|
|
617
706
|
let run: OrchestrationRun | null;
|
|
618
707
|
try {
|
|
619
|
-
run = readRun(resolved.taskDir);
|
|
708
|
+
run = readRun(resolved.taskDir, options);
|
|
620
709
|
} catch (error) {
|
|
621
710
|
return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
622
711
|
}
|
|
@@ -729,7 +818,7 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
729
818
|
function statusOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
730
819
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
731
820
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
732
|
-
const run = readRun(resolved.taskDir);
|
|
821
|
+
const run = readRun(resolved.taskDir, options);
|
|
733
822
|
if (!run) return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
|
|
734
823
|
return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
|
|
735
824
|
}
|
|
@@ -749,7 +838,15 @@ function prepareOrchestrationDelegationUnlocked(
|
|
|
749
838
|
if (!(options.supportsLifecycleDelegation ?? supportsLifecycleDelegation)(input.client)) {
|
|
750
839
|
return failed('ORCHESTRATION_CLIENT_UNSUPPORTED', `client '${input.client}' does not support lifecycle orchestration`, resolved.taskId);
|
|
751
840
|
}
|
|
752
|
-
|
|
841
|
+
emitDiagnostic(options, 'orchestration-prepare-start', {
|
|
842
|
+
taskId: resolved.taskId,
|
|
843
|
+
taskDir: resolved.taskDir,
|
|
844
|
+
repoRoot: resolved.repoRoot,
|
|
845
|
+
client: input.client,
|
|
846
|
+
requestedModel: input.requestedModel ?? null,
|
|
847
|
+
requestedReasoningEffort: input.requestedReasoningEffort ?? null
|
|
848
|
+
});
|
|
849
|
+
const run = readRun(resolved.taskDir, options);
|
|
753
850
|
if (!run || run.status !== 'running') return failed('ORCHESTRATION_RUN_NOT_RUNNING', 'a running orchestration is required', resolved.taskId);
|
|
754
851
|
if (run.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_BUSY', 'the run already has a pending delegation', resolved.taskId);
|
|
755
852
|
const repositoryPending = matchingDelegations(() => true, options);
|
|
@@ -862,7 +959,7 @@ function dispatchOrchestrationDelegationUnlocked(
|
|
|
862
959
|
): OrchestrationResult {
|
|
863
960
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
864
961
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
865
|
-
const run = readRun(resolved.taskDir);
|
|
962
|
+
const run = readRun(resolved.taskDir, options);
|
|
866
963
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
867
964
|
if (run.status !== 'running') {
|
|
868
965
|
return failed('ORCHESTRATION_STATE_INVALID', 'spawn dispatch requires a running orchestration', resolved.taskId);
|
|
@@ -908,16 +1005,42 @@ function matchingDelegations(
|
|
|
908
1005
|
const repoRoot = options.repoRoot ?? process.cwd();
|
|
909
1006
|
const activeRoot = path.join(repoRoot, '.agents', 'workspace', 'active');
|
|
910
1007
|
if (!fs.existsSync(activeRoot)) return [];
|
|
911
|
-
|
|
1008
|
+
emitDiagnostic(options, 'orchestration-active-scan-start', {
|
|
1009
|
+
activeRoot
|
|
1010
|
+
});
|
|
1011
|
+
const matches = fs.readdirSync(activeRoot, { withFileTypes: true })
|
|
912
1012
|
.filter((entry) => entry.isDirectory())
|
|
913
1013
|
.flatMap((entry) => {
|
|
914
|
-
const
|
|
1014
|
+
const candidateTaskId = entry.name;
|
|
1015
|
+
const candidateTaskDir = path.join(activeRoot, candidateTaskId);
|
|
1016
|
+
emitDiagnostic(options, 'orchestration-active-scan-candidate', {
|
|
1017
|
+
candidateTaskId,
|
|
1018
|
+
candidateTaskDir,
|
|
1019
|
+
orchestrationPath: orchestrationPath(candidateTaskDir)
|
|
1020
|
+
});
|
|
1021
|
+
let run: OrchestrationRun | null;
|
|
1022
|
+
try {
|
|
1023
|
+
run = readRun(candidateTaskDir, options);
|
|
1024
|
+
} catch (error) {
|
|
1025
|
+
emitDiagnostic(options, 'orchestration-active-scan-candidate-failed', {
|
|
1026
|
+
candidateTaskId,
|
|
1027
|
+
candidateTaskDir,
|
|
1028
|
+
errorType: error instanceof Error ? error.name : typeof error,
|
|
1029
|
+
reasonCodes: error instanceof OrchestrationStateError ? error.reasonCodes.join(',') : null
|
|
1030
|
+
});
|
|
1031
|
+
throw error;
|
|
1032
|
+
}
|
|
915
1033
|
if (!run || run.status !== 'running' || !run.pendingDelegation) return [];
|
|
916
1034
|
const receipt = run.pendingDelegation;
|
|
917
1035
|
return predicate(receipt)
|
|
918
|
-
? [{ taskId:
|
|
1036
|
+
? [{ taskId: candidateTaskId, run }]
|
|
919
1037
|
: [];
|
|
920
1038
|
});
|
|
1039
|
+
emitDiagnostic(options, 'orchestration-active-scan-finished', {
|
|
1040
|
+
activeRoot,
|
|
1041
|
+
matchingDelegations: matches.length
|
|
1042
|
+
});
|
|
1043
|
+
return matches;
|
|
921
1044
|
}
|
|
922
1045
|
|
|
923
1046
|
function uniqueMatchingDelegation(
|
|
@@ -1163,7 +1286,7 @@ function activateOrchestrationDelegation(
|
|
|
1163
1286
|
): OrchestrationResult {
|
|
1164
1287
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1165
1288
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1166
|
-
const run = readRun(resolved.taskDir);
|
|
1289
|
+
const run = readRun(resolved.taskDir, options);
|
|
1167
1290
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1168
1291
|
if (run.status !== 'running') {
|
|
1169
1292
|
return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
|
|
@@ -1191,7 +1314,7 @@ async function awaitOrchestrationDelegationActivation(
|
|
|
1191
1314
|
while (true) {
|
|
1192
1315
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1193
1316
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1194
|
-
const run = readRun(resolved.taskDir);
|
|
1317
|
+
const run = readRun(resolved.taskDir, options);
|
|
1195
1318
|
if (!run?.pendingDelegation) {
|
|
1196
1319
|
return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1197
1320
|
}
|
|
@@ -1257,7 +1380,7 @@ function recoverPreparedOrchestrationDelegation(
|
|
|
1257
1380
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1258
1381
|
try {
|
|
1259
1382
|
return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-orchestration.recover-prepared', () => {
|
|
1260
|
-
const run = readRun(resolved.taskDir);
|
|
1383
|
+
const run = readRun(resolved.taskDir, options);
|
|
1261
1384
|
const receipt = run?.pendingDelegation;
|
|
1262
1385
|
if (!run || !receipt) {
|
|
1263
1386
|
return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
@@ -1329,7 +1452,7 @@ function completeOrchestrationStage(
|
|
|
1329
1452
|
): OrchestrationResult {
|
|
1330
1453
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1331
1454
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1332
|
-
const run = readRun(resolved.taskDir);
|
|
1455
|
+
const run = readRun(resolved.taskDir, options);
|
|
1333
1456
|
if (!run) return { status: 'running', changed: false, taskId: resolved.taskId, run: null, next: null, error: null };
|
|
1334
1457
|
if (!run.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'active run has no pending delegation', resolved.taskId);
|
|
1335
1458
|
const result = completeDelegationStage(run.pendingDelegation, event);
|
|
@@ -1348,7 +1471,7 @@ function inspectOrchestrationStage(
|
|
|
1348
1471
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1349
1472
|
let run: OrchestrationRun | null;
|
|
1350
1473
|
try {
|
|
1351
|
-
run = readRun(resolved.taskDir);
|
|
1474
|
+
run = readRun(resolved.taskDir, options);
|
|
1352
1475
|
} catch (error) {
|
|
1353
1476
|
return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
1354
1477
|
}
|
|
@@ -1409,7 +1532,7 @@ function sealOrchestrationDelegation(
|
|
|
1409
1532
|
): OrchestrationResult {
|
|
1410
1533
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1411
1534
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1412
|
-
const run = readRun(resolved.taskDir);
|
|
1535
|
+
const run = readRun(resolved.taskDir, options);
|
|
1413
1536
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1414
1537
|
const result = sealDelegation(run.pendingDelegation, event, { now: options.now });
|
|
1415
1538
|
if (!result.ok) return pauseOrchestration(taskRef, result.code, result.message, true, options);
|
|
@@ -1421,7 +1544,7 @@ function sealOrchestrationDelegation(
|
|
|
1421
1544
|
function advanceOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
1422
1545
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1423
1546
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1424
|
-
const run = readRun(resolved.taskDir);
|
|
1547
|
+
const run = readRun(resolved.taskDir, options);
|
|
1425
1548
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1426
1549
|
const result = consumeDelegation(run.pendingDelegation, { now: options.now });
|
|
1427
1550
|
if (!result.ok) return pauseOrchestration(taskRef, result.code, result.message, true, options);
|
|
@@ -1448,7 +1571,7 @@ function pauseOrchestration(
|
|
|
1448
1571
|
): OrchestrationResult {
|
|
1449
1572
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1450
1573
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1451
|
-
const run = readRun(resolved.taskDir);
|
|
1574
|
+
const run = readRun(resolved.taskDir, options);
|
|
1452
1575
|
if (!run) return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
|
|
1453
1576
|
const updated = withUpdatedRun(run, { status: 'paused', pause: { code, message, recoverable } });
|
|
1454
1577
|
saveRun(resolved.taskDir, updated);
|