@zq-silk/yui 0.13.9 → 0.14.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/ARCHITECTURE.md +69 -428
- package/README.md +108 -298
- package/dist/agent/managedRuntimeEnvironment.js +2 -2
- package/dist/cli/commandCatalog.js +39 -77
- package/dist/cli/interactionCandidates.js +4 -4
- package/dist/cli/interactionPolicy.js +7 -10
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/updateCommand.js +6 -27
- package/dist/cli/updateOrchestrator.js +63 -484
- package/dist/cli/updatePorts.js +15 -333
- package/dist/cli/upgradeCommand.js +8 -65
- package/dist/cli.js +57 -242
- package/dist/commands/configCommands.js +11 -62
- package/dist/commands/executionAuditCommands.js +23 -23
- package/dist/commands/globalRoleCommands.js +2 -7
- package/dist/commands/jobCommands.js +1 -4
- package/dist/commands/projectCommands.js +5 -5
- package/dist/commands/releaseCommands.js +3 -10
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/sessionCommands.js +2 -2
- package/dist/commands/taskActor.js +31 -39
- package/dist/commands/taskChangeSetCommands.js +5 -12
- package/dist/commands/taskCommands.js +464 -1249
- package/dist/commands/taskContextCommand.js +35 -36
- package/dist/commands/taskExecutionCommands.js +33 -46
- package/dist/commands/taskInputCommands.js +20 -42
- package/dist/commands/taskNextActionCommand.js +9 -9
- package/dist/commands/taskOverviewCommand.js +56 -95
- package/dist/commands/taskRoleRuntimeStatus.js +77 -107
- package/dist/commands/taskUpstreamCommands.js +3 -3
- package/dist/commands/taskWorkspaceCommands.js +7 -79
- package/dist/commands/telemetryCommands.js +32 -124
- package/dist/commands/workflowCommands.js +3 -3
- package/dist/completion/fileCompletionManager.js +1 -1
- package/dist/config/configCatalog.js +4 -6
- package/dist/config/yuiConfig.js +6 -43
- package/dist/context/dispatchContext.js +14 -30
- package/dist/context/roleSessionContext.js +2 -2
- package/dist/context/sessionBootstrapManifest.js +2 -2
- package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
- package/dist/context/turnInputContract.js +204 -0
- package/dist/context/wakeNotification.js +2 -2
- package/dist/controller/agentRuntimeObserver.js +18 -18
- package/dist/controller/clientRuntime.js +13 -20
- package/dist/controller/controller.js +89 -116
- package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
- package/dist/controller/jobControl.js +17 -17
- package/dist/controller/resourceInventory.js +6 -6
- package/dist/controller/resourceInventoryLinux.js +38 -59
- package/dist/controller/resourceInventoryRpc.js +3 -3
- package/dist/controller/resourceInventoryWorker.js +1 -1
- package/dist/controller/runtime.js +46 -53
- package/dist/controller/runtimeEventInbox.js +23 -31
- package/dist/controller/runtimeEventProcessor.js +15 -15
- package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
- package/dist/controller/runtimeLaunchCoordinator.js +3 -3
- package/dist/controller/runtimeObservationHook.js +11 -8
- package/dist/controller/sessionNotify.js +11 -11
- package/dist/controller/structuredProviderObservation.js +89 -16
- package/dist/coordination/workMailbox.js +309 -579
- package/dist/coordination/workMailboxQueue.js +5 -6
- package/dist/core/controllerClient.js +1 -91
- package/dist/core/controllerServer.js +3 -6
- package/dist/doctor/doctor.js +51 -314
- package/dist/execution/candidateConvergence.js +3 -3
- package/dist/execution/executionGroup.js +32 -33
- package/dist/execution/executionHealth.js +36 -38
- package/dist/execution/resourceBroker.js +12 -12
- package/dist/executor/agentExecutor.js +30 -265
- package/dist/executor/effectiveLaunch.js +9 -19
- package/dist/executor/executorRegistry.js +43 -17
- package/dist/executor/fileRoleLaunchPlanner.js +56 -56
- package/dist/executor/launchPlan.js +3 -3
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +20 -25
- package/dist/input/inputRequest.js +12 -12
- package/dist/integration/changeSet.js +9 -13
- package/dist/integration/changeSetManifest.js +1 -1
- package/dist/integration/gitIntegrationService.js +2 -2
- package/dist/integration/integrationQueueService.js +5 -21
- package/dist/integration/overlapDiagnostics.js +2 -2
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/job/jobRunner.js +1 -1
- package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
- package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
- package/dist/message/message.js +6 -6
- package/dist/observability/executionAudit.js +74 -86
- package/dist/observability/faultClassification.js +7 -24
- package/dist/observability/orchestrationMetrics.js +5 -5
- package/dist/observability/runtimeIdentity.js +34 -101
- package/dist/profile/agentProfile.js +1 -1
- package/dist/release/cliHomeReleaseFence.js +3 -3
- package/dist/release/releaseWorkflowEngine.js +6 -10
- package/dist/release/releaseWorkflowPorts.js +2 -2
- package/dist/release/workflowFileLock.js +1 -1
- package/dist/repository/checkoutSwap.js +1 -1
- package/dist/repository/gitWorkspace.js +0 -13
- package/dist/repository/project.js +1 -1
- package/dist/repository/projectMaintenanceLock.js +1 -2
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +21 -25
- package/dist/repository/taskWorkspaceIdentity.js +8 -21
- package/dist/repository/taskWorkspacePreparer.js +63 -620
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +1 -1
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/sqliteResourceRegistry.js +1 -1
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewFindingLedger.js +1 -1
- package/dist/review/reviewOutcomeClassifier.js +35 -50
- package/dist/review/reviewRound.js +14 -25
- package/dist/review/reviewerAvailability.js +4 -4
- package/dist/review/taskFinalReviewContractResolution.js +41 -0
- package/dist/role/role.js +6 -3
- package/dist/runtime/agentDriver.js +4 -0
- package/dist/runtime/agentHost.js +151 -36
- package/dist/runtime/builtinAgentDrivers.js +79 -2
- package/dist/runtime/codexAppServerRuntime.js +122 -0
- package/dist/runtime/continuationManager.js +3 -5
- package/dist/runtime/exactControlPlane.js +17 -42
- package/dist/runtime/firstProgressAdvisory.js +1 -1
- package/dist/runtime/index.js +2 -2
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +4 -4
- package/dist/runtime/processExitObservation.js +1 -1
- package/dist/runtime/processExitOutbox.js +0 -32
- package/dist/runtime/promptEnvelope.js +9 -9
- package/dist/runtime/providerContinuation.js +2 -2
- package/dist/runtime/providerContinuationReconciliationService.js +2 -2
- package/dist/runtime/providerRuntimeIdentity.js +76 -24
- package/dist/runtime/recentTurnIds.js +38 -0
- package/dist/runtime/runtimeContinuationProjection.js +2 -2
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +58 -21
- package/dist/runtime/runtimeProjection.js +19 -27
- package/dist/runtime/sessionLaunchRequest.js +2 -2
- package/dist/runtime/structuredProviderHost.js +177 -12
- package/dist/runtime/tmuxAdapters.js +46 -11
- package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
- package/dist/scheduler/leaderWakeupProcessor.js +147 -445
- package/dist/scheduler/operatorEvent.js +4 -6
- package/dist/scheduler/resourceQueueProjection.js +71 -0
- package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
- package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
- package/dist/scheduler/taskExecutionProjection.js +99 -99
- package/dist/scheduler/taskObservabilityProjection.js +10 -10
- package/dist/scheduler/taskWake.js +4 -4
- package/dist/scheduler/wakeReason.js +6 -10
- package/dist/scheduler/wakeupQueue.js +0 -9
- package/dist/setup/setupCommand.js +2 -2
- package/dist/storage/currentTaskStore.js +46 -0
- package/dist/storage/persistenceWorker.js +1 -1
- package/dist/storage/sqliteSchema.js +81 -485
- package/dist/storage/sqliteStore.js +206 -365
- package/dist/storage/storageSchema.js +1 -15
- package/dist/storage/storageVersions.js +8 -9
- package/dist/storage/storeRpc.js +10 -34
- package/dist/storage/taskStore.js +63 -3415
- package/dist/storage/upgrade/recordVersions.js +55 -149
- package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
- package/dist/task/completionReadiness.js +5 -5
- package/dist/task/deliveryGuard.js +10 -10
- package/dist/task/nextAction.js +74 -77
- package/dist/task/task.js +2 -4
- package/dist/task/taskRecordReference.js +3 -3
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/telemetry/sqliteTelemetryStore.js +53 -53
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +8 -14
- package/dist/turn/turn.js +356 -0
- package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
- package/dist/verification/gateArtifactStore.js +2 -2
- package/dist/web/assets/client/app.js +1 -1
- package/dist/web/assets/client/components.js +29 -54
- package/dist/web/assets/client/i18n.js +17 -37
- package/dist/web/assets/client/view.js +37 -37
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +5 -5
- package/dist/web/assets/styles/widgets.js +1 -2
- package/dist/web/webSnapshot.js +65 -60
- package/dist/workItem/workItem.js +11 -11
- package/dist/workspace/workItemChangeSetManager.js +1 -1
- package/docs/task-local-identity.md +5 -5
- package/i18n/README.zh-CN.md +41 -54
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +85 -83
- package/skills/yui-operator/SKILL.md +16 -16
- package/skills/yui-reviewer/SKILL.md +10 -10
- package/skills/yui-runtime/SKILL.md +17 -18
- package/skills/yui-worker/SKILL.md +16 -18
- package/dist/context/runContextContract.js +0 -162
- package/dist/executor/turnCompletion.js +0 -126
- package/dist/review/taskFinalReviewContractEvent.js +0 -1
- package/dist/review/taskFinalReviewContractRebind.js +0 -367
- package/dist/run/agentRun.js +0 -356
- package/dist/run/rejectedYieldAttempt.js +0 -221
- package/dist/run/runControlRequest.js +0 -50
- package/dist/run/yieldReceipt.js +0 -65
- package/dist/runtime/turnCompletion.js +0 -3
- package/dist/scheduler/actionability.js +0 -323
- package/dist/scheduler/activeRoleRunDelivery.js +0 -868
- package/dist/scheduler/activeTaskProgress.js +0 -126
- package/dist/storage/compatibleTaskStore.js +0 -248
- package/dist/storage/migration/baseline.js +0 -78
- package/dist/storage/migration/classifier.js +0 -51
- package/dist/storage/migration/compatibleCodec.js +0 -53
- package/dist/storage/migration/engine.js +0 -147
- package/dist/storage/migration/index.js +0 -33
- package/dist/storage/migration/planner.js +0 -154
- package/dist/storage/migration/productionRegistry.js +0 -3931
- package/dist/storage/migration/registry.js +0 -169
- package/dist/storage/migration/report.js +0 -54
- package/dist/storage/migration/types.js +0 -31
- package/dist/storage/upgrade/homeClassification.js +0 -353
- package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
- package/dist/storage/upgrade/migrationReceipt.js +0 -67
- package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
- package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
- package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
- package/dist/storage/upgrade/recordVersionScan.js +0 -176
- package/dist/storage/upgrade/sqliteFileSet.js +0 -50
- package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
- package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
- package/dist/storage/upgrade/sqliteStateMigration.js +0 -918
- package/dist/storage/upgrade/switchProgress.js +0 -80
- package/dist/storage/upgrade/upgradeReceipt.js +0 -161
- package/dist/storage/upgradeCoordination.js +0 -187
- package/dist/storage/upgradeFence.js +0 -366
- package/dist/telemetry/telemetryCompaction.js +0 -252
package/dist/run/agentRun.js
DELETED
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
import { validateEffectiveLaunchSnapshot } from "../executor/effectiveLaunch.js";
|
|
2
|
-
import { formatAgentRunReceiptId, validateTaskRecordReference } from "../task/taskRecordReference.js";
|
|
3
|
-
import { validateYieldReceipt } from "./yieldReceipt.js";
|
|
4
|
-
import { validateAgentRunControlRequest } from "./runControlRequest.js";
|
|
5
|
-
import { validateManagedWorkspace } from "../worktree/managedWorkspace.js";
|
|
6
|
-
import { createRunAssignment, createRunBootstrapEnvelope, validateRunAssignment, validateRunBootstrapEnvelope } from "../context/runContextContract.js";
|
|
7
|
-
export function createAgentRun(id, taskId, roleName, mode, assignment, now, context) {
|
|
8
|
-
if (mode !== "new" && mode !== "resume") {
|
|
9
|
-
throw new Error(`Agent run dispatch mode is invalid: ${mode}.`);
|
|
10
|
-
}
|
|
11
|
-
const timestamp = now.toISOString();
|
|
12
|
-
const normalizedAssignment = typeof assignment === "string"
|
|
13
|
-
? createRunAssignment({
|
|
14
|
-
runId: id,
|
|
15
|
-
roleName,
|
|
16
|
-
purpose: context.purpose ?? "execution",
|
|
17
|
-
action: context.purpose === "review"
|
|
18
|
-
? "review-round"
|
|
19
|
-
: context.workItemId === undefined ? "leader-wake" : "execute-work-item",
|
|
20
|
-
subject: {
|
|
21
|
-
taskId,
|
|
22
|
-
...(context.workItemId === undefined ? {} : { workItemId: context.workItemId }),
|
|
23
|
-
...(context.purpose === "review"
|
|
24
|
-
? { reviewRoundId: context.reviewRoundId ?? `legacy-${id}` }
|
|
25
|
-
: context.reviewRoundId === undefined ? {} : { reviewRoundId: context.reviewRoundId })
|
|
26
|
-
},
|
|
27
|
-
directive: assignment,
|
|
28
|
-
deltaRefIds: []
|
|
29
|
-
})
|
|
30
|
-
: validateRunAssignment(assignment);
|
|
31
|
-
return {
|
|
32
|
-
schemaVersion: 10,
|
|
33
|
-
id: requireSafeIdentity(id, "Agent run id"),
|
|
34
|
-
taskId: requireSafeIdentity(taskId, "Task id"),
|
|
35
|
-
roleName: requireSafeIdentity(roleName, "Role name"),
|
|
36
|
-
mode,
|
|
37
|
-
assignment: normalizedAssignment,
|
|
38
|
-
bootstrapEnvelope: createRunBootstrapEnvelope(normalizedAssignment),
|
|
39
|
-
purpose: context.purpose ?? "execution",
|
|
40
|
-
...(context.workItemId === undefined
|
|
41
|
-
? {}
|
|
42
|
-
: { workItemId: requireSafeIdentity(context.workItemId, "Work item id") }),
|
|
43
|
-
...(context.reviewRoundId === undefined
|
|
44
|
-
? {}
|
|
45
|
-
: { reviewRoundId: requireSafeIdentity(context.reviewRoundId, "ReviewRound id") }),
|
|
46
|
-
...(context.executionGroupId === undefined
|
|
47
|
-
? {}
|
|
48
|
-
: { executionGroupId: requireSafeIdentity(context.executionGroupId, "ExecutionGroup id") }),
|
|
49
|
-
...(context.executionLaneId === undefined
|
|
50
|
-
? {}
|
|
51
|
-
: { executionLaneId: requireSafeIdentity(context.executionLaneId, "ExecutionLane id") }),
|
|
52
|
-
...(context.workspace === undefined
|
|
53
|
-
? {}
|
|
54
|
-
: { workspace: validateManagedWorkspace(context.workspace) }),
|
|
55
|
-
effective: validateEffectiveLaunchSnapshot(context.effective),
|
|
56
|
-
status: "active",
|
|
57
|
-
createdAt: timestamp,
|
|
58
|
-
updatedAt: timestamp
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
export function isActiveAgentRun(run) {
|
|
62
|
-
return run.status === "active";
|
|
63
|
-
}
|
|
64
|
-
/** Binds a freshly created, not-yet-persisted Run to its frozen Context. */
|
|
65
|
-
export function withAgentRunContextSnapshot(run, snapshot, deltaRefIds = []) {
|
|
66
|
-
if (run.status !== "active" || run.pushedAt !== undefined || run.deliveredAt !== undefined) {
|
|
67
|
-
throw new Error(`Cannot bind Context Snapshot after Run delivery: ${run.id}.`);
|
|
68
|
-
}
|
|
69
|
-
const assignment = createRunAssignment({
|
|
70
|
-
...run.assignment,
|
|
71
|
-
contextSnapshotRef: snapshot,
|
|
72
|
-
deltaRefIds
|
|
73
|
-
});
|
|
74
|
-
return validateAgentRun(Object.freeze({
|
|
75
|
-
...run,
|
|
76
|
-
assignment,
|
|
77
|
-
bootstrapEnvelope: createRunBootstrapEnvelope(assignment)
|
|
78
|
-
}));
|
|
79
|
-
}
|
|
80
|
-
export function markAgentRunPushed(run, now) {
|
|
81
|
-
if (run.status !== "active") {
|
|
82
|
-
throw new Error(`Cannot push a terminal Agent run: ${run.id}.`);
|
|
83
|
-
}
|
|
84
|
-
if (run.pushedAt !== undefined)
|
|
85
|
-
return run;
|
|
86
|
-
const timestamp = now.toISOString();
|
|
87
|
-
return { ...run, pushedAt: timestamp, updatedAt: timestamp };
|
|
88
|
-
}
|
|
89
|
-
export function markAgentRunDelivered(run, now) {
|
|
90
|
-
if (run.status !== "active") {
|
|
91
|
-
throw new Error(`Cannot deliver a terminal Agent run: ${run.id}.`);
|
|
92
|
-
}
|
|
93
|
-
if (run.deliveredAt !== undefined)
|
|
94
|
-
return run;
|
|
95
|
-
const timestamp = now.toISOString();
|
|
96
|
-
// Acceptance implies the prompt was pushed first; record both so a consumer
|
|
97
|
-
// never sees delivered-without-pushed.
|
|
98
|
-
return {
|
|
99
|
-
...run,
|
|
100
|
-
...(run.pushedAt === undefined ? { pushedAt: timestamp } : {}),
|
|
101
|
-
deliveredAt: timestamp,
|
|
102
|
-
updatedAt: timestamp
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
export function validateAgentRun(run) {
|
|
106
|
-
if (run.schemaVersion !== 10)
|
|
107
|
-
throw new Error("Agent run must use schemaVersion 10.");
|
|
108
|
-
validateTaskRecordReference({ taskId: run.taskId, localId: run.id }, "agentRun");
|
|
109
|
-
requireSafeIdentity(run.roleName, "Role name");
|
|
110
|
-
if (run.mode !== "new" && run.mode !== "resume") {
|
|
111
|
-
throw new Error(`Agent run dispatch mode is invalid: ${String(run.mode)}.`);
|
|
112
|
-
}
|
|
113
|
-
validateRunAssignment(run.assignment);
|
|
114
|
-
validateRunBootstrapEnvelope(run.bootstrapEnvelope);
|
|
115
|
-
if (run.assignment.runId !== run.id || run.assignment.roleName !== run.roleName
|
|
116
|
-
|| run.assignment.subject.taskId !== run.taskId) {
|
|
117
|
-
throw new Error("Agent run Assignment identity does not match the Run.");
|
|
118
|
-
}
|
|
119
|
-
if (JSON.stringify(createRunBootstrapEnvelope(run.assignment))
|
|
120
|
-
!== JSON.stringify(run.bootstrapEnvelope)) {
|
|
121
|
-
throw new Error("Agent run Bootstrap Envelope does not match its Assignment.");
|
|
122
|
-
}
|
|
123
|
-
if (!["execution", "review"].includes(run.purpose)) {
|
|
124
|
-
throw new Error(`Agent run purpose is invalid: ${String(run.purpose)}.`);
|
|
125
|
-
}
|
|
126
|
-
if (run.workItemId !== undefined) {
|
|
127
|
-
validateTaskRecordReference({ taskId: run.taskId, localId: run.workItemId }, "workItem");
|
|
128
|
-
}
|
|
129
|
-
if (run.reviewRoundId !== undefined) {
|
|
130
|
-
validateTaskRecordReference({ taskId: run.taskId, localId: run.reviewRoundId }, "reviewRound");
|
|
131
|
-
}
|
|
132
|
-
if ((run.executionGroupId === undefined) !== (run.executionLaneId === undefined)) {
|
|
133
|
-
throw new Error("Agent run execution lineage is incomplete.");
|
|
134
|
-
}
|
|
135
|
-
if (run.executionGroupId !== undefined) {
|
|
136
|
-
requireSafeIdentity(run.executionGroupId, "ExecutionGroup id");
|
|
137
|
-
requireSafeIdentity(run.executionLaneId, "ExecutionLane id");
|
|
138
|
-
}
|
|
139
|
-
if (run.workspace !== undefined) {
|
|
140
|
-
validateManagedWorkspace(run.workspace);
|
|
141
|
-
if (run.workspace.owner.taskId !== run.taskId) {
|
|
142
|
-
throw new Error("Agent run workspace belongs to another Task.");
|
|
143
|
-
}
|
|
144
|
-
if (run.workspace.owner.type === "work-item"
|
|
145
|
-
&& run.workspace.owner.workItemId !== run.workItemId) {
|
|
146
|
-
throw new Error("Agent run workspace belongs to another Work Item.");
|
|
147
|
-
}
|
|
148
|
-
if (run.workspace.owner.type === "work-item" && run.workItemId === undefined) {
|
|
149
|
-
throw new Error("A WorkItem workspace requires a WorkItem Agent run reference.");
|
|
150
|
-
}
|
|
151
|
-
if (run.workspace.owner.type === "review-round" && run.purpose !== "review") {
|
|
152
|
-
throw new Error("A ReviewRound workspace requires a review Agent run.");
|
|
153
|
-
}
|
|
154
|
-
if (run.workspace.owner.type === "integration-attempt") {
|
|
155
|
-
throw new Error("An IntegrationAttempt workspace cannot be used by an Agent run.");
|
|
156
|
-
}
|
|
157
|
-
if (run.workspace.owner.type === "execution-lane") {
|
|
158
|
-
if (run.workspace.owner.executionGroupId !== run.executionGroupId
|
|
159
|
-
|| run.workspace.owner.executionLaneId !== run.executionLaneId) {
|
|
160
|
-
throw new Error("Agent run Execution Lane workspace lineage does not match the Run.");
|
|
161
|
-
}
|
|
162
|
-
if (run.workspace.owner.purpose === "execution"
|
|
163
|
-
&& run.workspace.owner.workItemId !== run.workItemId) {
|
|
164
|
-
throw new Error("Agent run Execution Lane workspace WorkItem does not match the Run.");
|
|
165
|
-
}
|
|
166
|
-
if (run.workspace.owner.purpose === "review"
|
|
167
|
-
&& run.workspace.owner.reviewRoundId !== run.reviewRoundId) {
|
|
168
|
-
throw new Error("Agent run review Lane workspace ReviewRound does not match the Run.");
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if (run.workspace.owner.type === "review-round"
|
|
172
|
-
&& run.workspace.owner.reviewRoundId !== run.reviewRoundId) {
|
|
173
|
-
throw new Error(`Agent run ReviewRound workspace owner does not match ${run.reviewRoundId ?? "none"}.`);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (run.purpose === "review") {
|
|
177
|
-
if (run.reviewRoundId === undefined) {
|
|
178
|
-
throw new Error("A review Agent run requires a ReviewRound reference.");
|
|
179
|
-
}
|
|
180
|
-
if (run.workspace === undefined
|
|
181
|
-
|| !((run.workspace.owner.type === "review-round"
|
|
182
|
-
&& run.workspace.owner.reviewRoundId === run.reviewRoundId)
|
|
183
|
-
|| (run.workspace.owner.type === "execution-lane"
|
|
184
|
-
&& run.workspace.owner.purpose === "review"
|
|
185
|
-
&& run.workspace.owner.reviewRoundId === run.reviewRoundId))) {
|
|
186
|
-
throw new Error(`A review Agent run requires its exact ReviewRound workspace owner: ${run.reviewRoundId}.`);
|
|
187
|
-
}
|
|
188
|
-
if (run.workspace.entries.length === 0
|
|
189
|
-
|| run.workspace.entries.some(({ access }) => access !== "write")) {
|
|
190
|
-
throw new Error("A review Agent run requires only isolated writable workspace entries.");
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
if (run.reviewRoundId !== undefined) {
|
|
195
|
-
throw new Error("An execution Agent run cannot reference a ReviewRound.");
|
|
196
|
-
}
|
|
197
|
-
if (run.workspace?.owner.type === "review-round") {
|
|
198
|
-
throw new Error("An execution Agent run cannot use a ReviewRound-owned workspace.");
|
|
199
|
-
}
|
|
200
|
-
if (run.workspace?.owner.type === "execution-lane" && run.workspace.owner.purpose !== "execution") {
|
|
201
|
-
throw new Error("An execution Agent run cannot use a review Lane workspace.");
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
validateEffectiveLaunchSnapshot(run.effective);
|
|
205
|
-
if (run.workspace !== undefined
|
|
206
|
-
&& (run.effective.workspace.root !== run.workspace.root
|
|
207
|
-
|| JSON.stringify(run.effective.workspace.entries) !== JSON.stringify(run.workspace.entries))) {
|
|
208
|
-
throw new Error("Agent run effective workspace does not match its managed workspace.");
|
|
209
|
-
}
|
|
210
|
-
if (run.purpose === "review") {
|
|
211
|
-
if (run.effective.reviewRoundId !== run.reviewRoundId) {
|
|
212
|
-
throw new Error("Review Agent run effective provenance does not match its ReviewRound.");
|
|
213
|
-
}
|
|
214
|
-
if (!run.workspace.entries.some(({ baseCommit }) => baseCommit === run.effective.reviewBaseCommit)) {
|
|
215
|
-
throw new Error("Review Agent run effective base does not match its workspace.");
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
else if (run.effective.reviewRoundId !== undefined) {
|
|
219
|
-
throw new Error("Execution Agent run cannot carry Review effective provenance.");
|
|
220
|
-
}
|
|
221
|
-
if (!["active", "yielded", "failed"].includes(run.status)) {
|
|
222
|
-
throw new Error(`Agent run status is invalid: ${String(run.status)}.`);
|
|
223
|
-
}
|
|
224
|
-
requireTimestamp(run.createdAt, "Agent run createdAt");
|
|
225
|
-
requireTimestamp(run.updatedAt, "Agent run updatedAt");
|
|
226
|
-
if (run.pushedAt !== undefined)
|
|
227
|
-
requireTimestamp(run.pushedAt, "Agent run pushedAt");
|
|
228
|
-
if (run.deliveredAt !== undefined) {
|
|
229
|
-
requireTimestamp(run.deliveredAt, "Agent run deliveredAt");
|
|
230
|
-
// Acceptance can never precede its transport push.
|
|
231
|
-
if (run.pushedAt === undefined) {
|
|
232
|
-
throw new Error("Agent run deliveredAt requires a prior pushedAt.");
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (run.deliveryReceiptId !== undefined) {
|
|
236
|
-
requireText(run.deliveryReceiptId, "Agent run deliveryReceiptId");
|
|
237
|
-
if (run.deliveryReceiptId.length > 256) {
|
|
238
|
-
throw new Error("Agent run deliveryReceiptId exceeds 256 characters.");
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
if (run.status === "active") {
|
|
242
|
-
if (run.summary !== undefined || run.endedAt !== undefined) {
|
|
243
|
-
throw new Error("An active Agent run cannot have terminal metadata.");
|
|
244
|
-
}
|
|
245
|
-
if (run.disposition !== undefined
|
|
246
|
-
|| run.observedActionabilityDigest !== undefined
|
|
247
|
-
|| run.waitReason !== undefined) {
|
|
248
|
-
throw new Error("An active Agent run cannot carry Leader receipt metadata.");
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
requireText(run.summary ?? "", "Agent run summary");
|
|
253
|
-
requireTimestamp(run.endedAt ?? "", "Agent run endedAt");
|
|
254
|
-
if (run.disposition !== undefined
|
|
255
|
-
&& !["progress", "waiting", "blocked", "completed"].includes(run.disposition)) {
|
|
256
|
-
throw new Error(`Agent run disposition is invalid: ${String(run.disposition)}.`);
|
|
257
|
-
}
|
|
258
|
-
if (run.observedActionabilityDigest !== undefined) {
|
|
259
|
-
requireText(run.observedActionabilityDigest, "Agent run observedActionabilityDigest");
|
|
260
|
-
}
|
|
261
|
-
if (run.waitReason !== undefined) {
|
|
262
|
-
requireText(run.waitReason.kind, "Agent run waitReason kind");
|
|
263
|
-
if (run.waitReason.ref !== undefined) {
|
|
264
|
-
requireText(run.waitReason.ref, "Agent run waitReason ref");
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
if (run.controlRequest !== undefined) {
|
|
269
|
-
validateAgentRunControlRequest(run.controlRequest);
|
|
270
|
-
if (run.status !== "active") {
|
|
271
|
-
throw new Error("A terminal Agent run cannot carry a controlRequest projection.");
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (run.yieldReceipt !== undefined) {
|
|
275
|
-
validateYieldReceipt(run.yieldReceipt);
|
|
276
|
-
if (run.status !== "yielded") {
|
|
277
|
-
throw new Error("An Agent run yield receipt requires a yielded Run.");
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return run;
|
|
281
|
-
}
|
|
282
|
-
export function yieldAgentRun(run, summary, now) {
|
|
283
|
-
return finishAgentRun(run, "yielded", requireResultText(summary, "Agent run summary"), now);
|
|
284
|
-
}
|
|
285
|
-
export function failAgentRun(run, summary, now) {
|
|
286
|
-
return finishAgentRun(run, "failed", requireResultText(summary, "Agent run summary"), now);
|
|
287
|
-
}
|
|
288
|
-
function finishAgentRun(run, status, summary, now) {
|
|
289
|
-
if (run.status !== "active") {
|
|
290
|
-
throw new Error(`Agent run is already terminal: ${run.id}.`);
|
|
291
|
-
}
|
|
292
|
-
const timestamp = now.toISOString();
|
|
293
|
-
const terminal = {
|
|
294
|
-
...run,
|
|
295
|
-
status,
|
|
296
|
-
summary,
|
|
297
|
-
updatedAt: timestamp,
|
|
298
|
-
endedAt: timestamp
|
|
299
|
-
};
|
|
300
|
-
if (terminal.controlRequest !== undefined)
|
|
301
|
-
delete terminal.controlRequest;
|
|
302
|
-
return terminal;
|
|
303
|
-
}
|
|
304
|
-
export function agentRunDeliveryReceiptId(run) {
|
|
305
|
-
return run.deliveryReceiptId
|
|
306
|
-
?? run.controlRequest?.receiptId
|
|
307
|
-
?? formatAgentRunReceiptId(run.taskId, run.id);
|
|
308
|
-
}
|
|
309
|
-
export function withAgentRunControlRequest(run, request, now) {
|
|
310
|
-
if (run.status !== "active") {
|
|
311
|
-
throw new Error(`Agent run cannot accept a control request: ${run.id}.`);
|
|
312
|
-
}
|
|
313
|
-
return validateAgentRun({
|
|
314
|
-
...run,
|
|
315
|
-
mode: "resume",
|
|
316
|
-
deliveryReceiptId: request.receiptId,
|
|
317
|
-
controlRequest: validateAgentRunControlRequest(request),
|
|
318
|
-
updatedAt: now.toISOString()
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
/** Attaches the Issue 04 yield receipt to a yielded Run. */
|
|
322
|
-
export function withYieldReceipt(run, receipt) {
|
|
323
|
-
if (run.status !== "yielded") {
|
|
324
|
-
throw new Error(`Cannot attach a yield receipt to a non-yielded Agent run: ${run.id}.`);
|
|
325
|
-
}
|
|
326
|
-
return validateAgentRun({ ...run, yieldReceipt: receipt });
|
|
327
|
-
}
|
|
328
|
-
function requireSafeIdentity(value, label) {
|
|
329
|
-
const normalized = requireText(value, label);
|
|
330
|
-
if (["__proto__", "prototype", "constructor", ".", ".."].includes(normalized)
|
|
331
|
-
|| /[\/\\\0]/.test(normalized)) {
|
|
332
|
-
throw new Error(`${label} is invalid.`);
|
|
333
|
-
}
|
|
334
|
-
return normalized;
|
|
335
|
-
}
|
|
336
|
-
function requireText(value, label) {
|
|
337
|
-
if (typeof value !== "string" || value.includes("\0"))
|
|
338
|
-
throw new Error(`${label} is invalid.`);
|
|
339
|
-
const normalized = value.trim();
|
|
340
|
-
if (normalized.length === 0)
|
|
341
|
-
throw new Error(`${label} is required.`);
|
|
342
|
-
return normalized;
|
|
343
|
-
}
|
|
344
|
-
/** Result transport preserves the provider's complete text, including outer whitespace. */
|
|
345
|
-
function requireResultText(value, label) {
|
|
346
|
-
if (typeof value !== "string" || value.includes("\0"))
|
|
347
|
-
throw new Error(`${label} is invalid.`);
|
|
348
|
-
if (value.trim().length === 0)
|
|
349
|
-
throw new Error(`${label} is required.`);
|
|
350
|
-
return value;
|
|
351
|
-
}
|
|
352
|
-
function requireTimestamp(value, label) {
|
|
353
|
-
if (typeof value !== "string" || !Number.isFinite(Date.parse(value))) {
|
|
354
|
-
throw new Error(`${label} must be an ISO timestamp.`);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import { contextContentDigest, validateContextSnapshotRef } from "../context/contextSnapshot.js";
|
|
2
|
-
import { computeYieldOutcomeDigest } from "./yieldReceipt.js";
|
|
3
|
-
export const RUN_YIELD_REJECTED_EVENT = "run.yield-rejected";
|
|
4
|
-
const MAX_SUMMARY_CHARACTERS = 2_000;
|
|
5
|
-
const MAX_REPORT_CHARACTERS = 8_000;
|
|
6
|
-
const MAX_CHECKS = 16;
|
|
7
|
-
const MAX_FINDINGS = 16;
|
|
8
|
-
const MAX_EVIDENCE = 16;
|
|
9
|
-
const MAX_LABEL_CHARACTERS = 128;
|
|
10
|
-
const MAX_DETAILS_CHARACTERS = 512;
|
|
11
|
-
const MAX_EVIDENCE_CHARACTERS = 512;
|
|
12
|
-
/**
|
|
13
|
-
* Creates the bounded diagnostic projection persisted when a Reviewer report
|
|
14
|
-
* cannot cross the exact terminalization fence. The full validated submission
|
|
15
|
-
* participates in the immutable digest, while only known, size-bounded fields
|
|
16
|
-
* are retained as non-authoritative evidence.
|
|
17
|
-
*/
|
|
18
|
-
export function createRejectedYieldAttempt(input) {
|
|
19
|
-
const reviewResult = input.reviewResult;
|
|
20
|
-
const fullReport = reviewResult?.report ?? input.summary;
|
|
21
|
-
const contentDigest = computeYieldOutcomeDigest({
|
|
22
|
-
status: "yielded",
|
|
23
|
-
summary: input.summary,
|
|
24
|
-
...(reviewResult === undefined ? {} : { reviewResult })
|
|
25
|
-
});
|
|
26
|
-
const summary = boundedText(input.summary, MAX_SUMMARY_CHARACTERS);
|
|
27
|
-
const report = boundedText(fullReport, MAX_REPORT_CHARACTERS);
|
|
28
|
-
const checks = (reviewResult?.checks ?? []).slice(0, MAX_CHECKS).map((check) => ({
|
|
29
|
-
name: boundedText(check.name, MAX_LABEL_CHARACTERS),
|
|
30
|
-
outcome: check.outcome,
|
|
31
|
-
...(check.details === undefined
|
|
32
|
-
? {}
|
|
33
|
-
: { details: boundedText(check.details, MAX_DETAILS_CHARACTERS) })
|
|
34
|
-
}));
|
|
35
|
-
const findings = (reviewResult?.findings ?? []).slice(0, MAX_FINDINGS).map((finding) => ({
|
|
36
|
-
id: boundedText(finding.id, MAX_LABEL_CHARACTERS),
|
|
37
|
-
severity: finding.severity,
|
|
38
|
-
status: finding.status,
|
|
39
|
-
summary: boundedText(finding.summary, MAX_DETAILS_CHARACTERS)
|
|
40
|
-
}));
|
|
41
|
-
const evidence = (reviewResult?.evidence ?? []).slice(0, MAX_EVIDENCE)
|
|
42
|
-
.map((entry) => boundedText(entry, MAX_EVIDENCE_CHARACTERS));
|
|
43
|
-
const deltaReasoning = reviewResult?.deltaReasoning === undefined
|
|
44
|
-
? undefined
|
|
45
|
-
: boundedText(reviewResult.deltaReasoning, MAX_DETAILS_CHARACTERS);
|
|
46
|
-
const projectionTruncated = summary !== input.summary
|
|
47
|
-
|| report !== fullReport
|
|
48
|
-
|| checks.length !== (reviewResult?.checks?.length ?? 0)
|
|
49
|
-
|| checks.some((check, index) => (check.name !== reviewResult?.checks?.[index]?.name
|
|
50
|
-
|| check.details !== reviewResult?.checks?.[index]?.details))
|
|
51
|
-
|| findings.length !== (reviewResult?.findings?.length ?? 0)
|
|
52
|
-
|| findings.some((finding, index) => (finding.id !== reviewResult?.findings?.[index]?.id
|
|
53
|
-
|| finding.summary !== reviewResult?.findings?.[index]?.summary))
|
|
54
|
-
|| evidence.length !== (reviewResult?.evidence?.length ?? 0)
|
|
55
|
-
|| evidence.some((entry, index) => entry !== reviewResult?.evidence?.[index])
|
|
56
|
-
|| deltaReasoning !== reviewResult?.deltaReasoning
|
|
57
|
-
|| reviewResult?.gitSnapshot !== undefined;
|
|
58
|
-
const observed = Object.freeze({
|
|
59
|
-
nativeSessionId: input.nativeSessionId ?? null,
|
|
60
|
-
launchId: input.launchId ?? null,
|
|
61
|
-
durableNativeSessionId: input.durableNativeSessionId ?? null,
|
|
62
|
-
durableLaunchId: input.durableLaunchId ?? null,
|
|
63
|
-
inFlightRunId: input.inFlightRunId ?? null,
|
|
64
|
-
inFlightReceiptId: input.inFlightReceiptId ?? null,
|
|
65
|
-
activeRunId: input.activeRun?.id ?? null,
|
|
66
|
-
activeReceiptId: input.activeRun?.receiptId ?? null,
|
|
67
|
-
contextSnapshot: input.contextSnapshot ?? null,
|
|
68
|
-
activeContextSnapshot: input.activeRun?.contextSnapshot ?? null
|
|
69
|
-
});
|
|
70
|
-
const attemptDigest = contextContentDigest({
|
|
71
|
-
taskId: input.taskId,
|
|
72
|
-
runId: input.runId,
|
|
73
|
-
reviewRoundId: input.reviewRoundId,
|
|
74
|
-
receiptId: input.receiptId,
|
|
75
|
-
rejectionReason: input.rejectionReason,
|
|
76
|
-
contentDigest,
|
|
77
|
-
observed
|
|
78
|
-
});
|
|
79
|
-
return Object.freeze({
|
|
80
|
-
schemaVersion: 1,
|
|
81
|
-
authority: "unaccepted",
|
|
82
|
-
semanticStatus: "diagnostic-only",
|
|
83
|
-
taskId: input.taskId,
|
|
84
|
-
runId: input.runId,
|
|
85
|
-
roleName: input.roleName,
|
|
86
|
-
purpose: "review",
|
|
87
|
-
reviewRoundId: input.reviewRoundId,
|
|
88
|
-
receiptId: input.receiptId,
|
|
89
|
-
rejectionReason: input.rejectionReason,
|
|
90
|
-
summary,
|
|
91
|
-
report,
|
|
92
|
-
checks: Object.freeze(checks),
|
|
93
|
-
findings: Object.freeze(findings),
|
|
94
|
-
evidence: Object.freeze(evidence),
|
|
95
|
-
...(reviewResult?.evidenceCommit === undefined
|
|
96
|
-
? {}
|
|
97
|
-
: { evidenceCommit: reviewResult.evidenceCommit }),
|
|
98
|
-
...(reviewResult?.deltaDisposition === undefined
|
|
99
|
-
? {}
|
|
100
|
-
: { deltaDisposition: reviewResult.deltaDisposition }),
|
|
101
|
-
...(deltaReasoning === undefined ? {} : { deltaReasoning }),
|
|
102
|
-
projectionTruncated,
|
|
103
|
-
observed,
|
|
104
|
-
attemptedAt: input.attemptedAt.toISOString(),
|
|
105
|
-
contentDigest,
|
|
106
|
-
attemptDigest
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
export function rejectedYieldAttemptEventPayload(attempt) {
|
|
110
|
-
return {
|
|
111
|
-
runId: attempt.runId,
|
|
112
|
-
roleName: attempt.roleName,
|
|
113
|
-
reviewRoundId: attempt.reviewRoundId,
|
|
114
|
-
receiptId: attempt.receiptId,
|
|
115
|
-
rejectionReason: attempt.rejectionReason,
|
|
116
|
-
authority: attempt.authority,
|
|
117
|
-
semanticStatus: attempt.semanticStatus,
|
|
118
|
-
contentDigest: attempt.contentDigest,
|
|
119
|
-
attemptDigest: attempt.attemptDigest,
|
|
120
|
-
attempt: JSON.stringify(attempt)
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/** Reads only canonical records emitted by rejectedYieldAttemptEventPayload. */
|
|
124
|
-
export function rejectedYieldAttemptFromTaskEvent(event) {
|
|
125
|
-
if (event.type !== RUN_YIELD_REJECTED_EVENT)
|
|
126
|
-
return null;
|
|
127
|
-
try {
|
|
128
|
-
const parsed = JSON.parse(event.payload.attempt ?? "");
|
|
129
|
-
if (!isRejectedYieldAttempt(parsed))
|
|
130
|
-
return null;
|
|
131
|
-
const expectedAttemptDigest = contextContentDigest({
|
|
132
|
-
taskId: parsed.taskId,
|
|
133
|
-
runId: parsed.runId,
|
|
134
|
-
reviewRoundId: parsed.reviewRoundId,
|
|
135
|
-
receiptId: parsed.receiptId,
|
|
136
|
-
rejectionReason: parsed.rejectionReason,
|
|
137
|
-
contentDigest: parsed.contentDigest,
|
|
138
|
-
observed: parsed.observed
|
|
139
|
-
});
|
|
140
|
-
if (parsed.schemaVersion !== 1
|
|
141
|
-
|| parsed.authority !== "unaccepted"
|
|
142
|
-
|| parsed.semanticStatus !== "diagnostic-only"
|
|
143
|
-
|| parsed.purpose !== "review"
|
|
144
|
-
|| parsed.taskId !== event.taskId
|
|
145
|
-
|| parsed.runId !== event.payload.runId
|
|
146
|
-
|| parsed.roleName !== event.payload.roleName
|
|
147
|
-
|| parsed.reviewRoundId !== event.payload.reviewRoundId
|
|
148
|
-
|| parsed.receiptId !== event.payload.receiptId
|
|
149
|
-
|| parsed.rejectionReason !== event.payload.rejectionReason
|
|
150
|
-
|| parsed.contentDigest !== event.payload.contentDigest
|
|
151
|
-
|| parsed.attemptDigest !== event.payload.attemptDigest
|
|
152
|
-
|| parsed.attemptDigest !== expectedAttemptDigest
|
|
153
|
-
|| parsed.attemptedAt !== event.createdAt
|
|
154
|
-
|| !/^[a-f0-9]{64}$/u.test(parsed.contentDigest)) {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
return parsed;
|
|
158
|
-
}
|
|
159
|
-
catch {
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
function isRejectedYieldAttempt(value) {
|
|
164
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
165
|
-
return false;
|
|
166
|
-
const attempt = value;
|
|
167
|
-
const observed = attempt.observed;
|
|
168
|
-
if (typeof observed !== "object" || observed === null || Array.isArray(observed))
|
|
169
|
-
return false;
|
|
170
|
-
const nullableObserved = [
|
|
171
|
-
observed.nativeSessionId,
|
|
172
|
-
observed.launchId,
|
|
173
|
-
observed.durableNativeSessionId,
|
|
174
|
-
observed.durableLaunchId,
|
|
175
|
-
observed.inFlightRunId,
|
|
176
|
-
observed.inFlightReceiptId,
|
|
177
|
-
observed.activeRunId,
|
|
178
|
-
observed.activeReceiptId
|
|
179
|
-
];
|
|
180
|
-
if (nullableObserved.some((entry) => entry !== null && typeof entry !== "string")) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
if (observed.contextSnapshot !== null)
|
|
184
|
-
validateContextSnapshotRef(observed.contextSnapshot);
|
|
185
|
-
if (observed.activeContextSnapshot !== null) {
|
|
186
|
-
validateContextSnapshotRef(observed.activeContextSnapshot);
|
|
187
|
-
}
|
|
188
|
-
return typeof attempt.taskId === "string"
|
|
189
|
-
&& typeof attempt.runId === "string"
|
|
190
|
-
&& typeof attempt.roleName === "string"
|
|
191
|
-
&& typeof attempt.reviewRoundId === "string"
|
|
192
|
-
&& typeof attempt.receiptId === "string"
|
|
193
|
-
&& typeof attempt.rejectionReason === "string"
|
|
194
|
-
&& typeof attempt.summary === "string"
|
|
195
|
-
&& typeof attempt.report === "string"
|
|
196
|
-
&& typeof attempt.projectionTruncated === "boolean"
|
|
197
|
-
&& typeof attempt.attemptedAt === "string"
|
|
198
|
-
&& typeof attempt.contentDigest === "string"
|
|
199
|
-
&& typeof attempt.attemptDigest === "string"
|
|
200
|
-
&& Array.isArray(attempt.checks)
|
|
201
|
-
&& attempt.checks.every((check) => (typeof check === "object" && check !== null
|
|
202
|
-
&& typeof check.name === "string"
|
|
203
|
-
&& ["passed", "failed", "skipped"].includes(check.outcome)
|
|
204
|
-
&& (check.details === undefined || typeof check.details === "string")))
|
|
205
|
-
&& Array.isArray(attempt.findings)
|
|
206
|
-
&& attempt.findings.every((finding) => (typeof finding === "object" && finding !== null
|
|
207
|
-
&& typeof finding.id === "string"
|
|
208
|
-
&& typeof finding.summary === "string"))
|
|
209
|
-
&& Array.isArray(attempt.evidence)
|
|
210
|
-
&& attempt.evidence.every((entry) => typeof entry === "string");
|
|
211
|
-
}
|
|
212
|
-
function boundedText(value, maximum) {
|
|
213
|
-
const safe = value
|
|
214
|
-
.replaceAll(/\u001B\][^\u0007]*(?:\u0007|\u001B\\|\u009C)/gu, " ")
|
|
215
|
-
.replaceAll(/\u001B\[[0-?]*[ -/]*[@-~]/gu, " ")
|
|
216
|
-
.replaceAll(/[\u0000-\u0008\u000B-\u001F\u007F-\u009F]/gu, " ");
|
|
217
|
-
const characters = Array.from(safe);
|
|
218
|
-
if (characters.length <= maximum)
|
|
219
|
-
return safe;
|
|
220
|
-
return `${characters.slice(0, maximum - 1).join("")}…`;
|
|
221
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { requireIdentity, requireTimestamp } from "../domain/validation.js";
|
|
3
|
-
export const WORKFLOW_OUTCOME_REQUEST_TIMEOUT_MS = 30_000;
|
|
4
|
-
export function createWorkflowOutcomeRequest(input) {
|
|
5
|
-
const requestedAt = input.now.toISOString();
|
|
6
|
-
return validateAgentRunControlRequest({
|
|
7
|
-
schemaVersion: 1,
|
|
8
|
-
kind: "workflow-outcome",
|
|
9
|
-
requestId: createHash("sha256")
|
|
10
|
-
.update(`${input.runId}\0${input.nativeTurnId}\0${requestedAt}`)
|
|
11
|
-
.digest("hex"),
|
|
12
|
-
state: "dispatching",
|
|
13
|
-
nativeTurnId: input.nativeTurnId,
|
|
14
|
-
receiptId: `workflow-outcome-${input.runId}-${input.nativeTurnId}`,
|
|
15
|
-
requestedAt,
|
|
16
|
-
deadlineAt: new Date(input.now.getTime() + WORKFLOW_OUTCOME_REQUEST_TIMEOUT_MS).toISOString()
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
export function validateAgentRunControlRequest(value) {
|
|
20
|
-
if (value.schemaVersion !== 1 || value.kind !== "workflow-outcome") {
|
|
21
|
-
throw new Error("Agent Run control request is unsupported.");
|
|
22
|
-
}
|
|
23
|
-
if (value.state !== "dispatching" && value.state !== "awaiting-outcome") {
|
|
24
|
-
throw new Error("Agent Run control request state is invalid.");
|
|
25
|
-
}
|
|
26
|
-
requireIdentity(value.requestId, "Agent Run control request id");
|
|
27
|
-
requireIdentity(value.nativeTurnId, "Agent Run control native Turn id");
|
|
28
|
-
requireIdentity(value.receiptId, "Agent Run control receipt id");
|
|
29
|
-
requireTimestamp(value.requestedAt, "Agent Run control requestedAt");
|
|
30
|
-
requireTimestamp(value.deadlineAt, "Agent Run control deadlineAt");
|
|
31
|
-
if (Date.parse(value.deadlineAt) <= Date.parse(value.requestedAt)) {
|
|
32
|
-
throw new Error("Agent Run control deadline must follow requestedAt.");
|
|
33
|
-
}
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
export function markWorkflowOutcomeRequestDispatched(value) {
|
|
37
|
-
validateAgentRunControlRequest(value);
|
|
38
|
-
return value.state === "dispatching"
|
|
39
|
-
? validateAgentRunControlRequest({ ...value, state: "awaiting-outcome" })
|
|
40
|
-
: value;
|
|
41
|
-
}
|
|
42
|
-
export function serializeWorkflowOutcomeRequestEnvelope(input) {
|
|
43
|
-
validateAgentRunControlRequest(input.request);
|
|
44
|
-
return [
|
|
45
|
-
"Yui managed workflow-outcome request for the existing Run.",
|
|
46
|
-
`task=${requireIdentity(input.taskId, "Task id")} run=${requireIdentity(input.runId, "Run id")} role=${requireIdentity(input.roleName, "Role name")}`,
|
|
47
|
-
`request=${input.request.requestId} completedTurn=${input.request.nativeTurnId}`,
|
|
48
|
-
"Record the required Yui workflow outcome now. Do not replay the Assignment or repeat completed work."
|
|
49
|
-
].join("\n");
|
|
50
|
-
}
|