@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.
Files changed (229) hide show
  1. package/ARCHITECTURE.md +69 -428
  2. package/README.md +108 -298
  3. package/dist/agent/managedRuntimeEnvironment.js +2 -2
  4. package/dist/cli/commandCatalog.js +39 -77
  5. package/dist/cli/interactionCandidates.js +4 -4
  6. package/dist/cli/interactionPolicy.js +7 -10
  7. package/dist/cli/invocationRouter.js +1 -1
  8. package/dist/cli/updateCommand.js +6 -27
  9. package/dist/cli/updateOrchestrator.js +63 -484
  10. package/dist/cli/updatePorts.js +15 -333
  11. package/dist/cli/upgradeCommand.js +8 -65
  12. package/dist/cli.js +57 -242
  13. package/dist/commands/configCommands.js +11 -62
  14. package/dist/commands/executionAuditCommands.js +23 -23
  15. package/dist/commands/globalRoleCommands.js +2 -7
  16. package/dist/commands/jobCommands.js +1 -4
  17. package/dist/commands/projectCommands.js +5 -5
  18. package/dist/commands/releaseCommands.js +3 -10
  19. package/dist/commands/resourcesCommands.js +2 -2
  20. package/dist/commands/sessionCommands.js +2 -2
  21. package/dist/commands/taskActor.js +31 -39
  22. package/dist/commands/taskChangeSetCommands.js +5 -12
  23. package/dist/commands/taskCommands.js +464 -1249
  24. package/dist/commands/taskContextCommand.js +35 -36
  25. package/dist/commands/taskExecutionCommands.js +33 -46
  26. package/dist/commands/taskInputCommands.js +20 -42
  27. package/dist/commands/taskNextActionCommand.js +9 -9
  28. package/dist/commands/taskOverviewCommand.js +56 -95
  29. package/dist/commands/taskRoleRuntimeStatus.js +77 -107
  30. package/dist/commands/taskUpstreamCommands.js +3 -3
  31. package/dist/commands/taskWorkspaceCommands.js +7 -79
  32. package/dist/commands/telemetryCommands.js +32 -124
  33. package/dist/commands/workflowCommands.js +3 -3
  34. package/dist/completion/fileCompletionManager.js +1 -1
  35. package/dist/config/configCatalog.js +4 -6
  36. package/dist/config/yuiConfig.js +6 -43
  37. package/dist/context/dispatchContext.js +14 -30
  38. package/dist/context/roleSessionContext.js +2 -2
  39. package/dist/context/sessionBootstrapManifest.js +2 -2
  40. package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
  41. package/dist/context/turnInputContract.js +204 -0
  42. package/dist/context/wakeNotification.js +2 -2
  43. package/dist/controller/agentRuntimeObserver.js +18 -18
  44. package/dist/controller/clientRuntime.js +13 -20
  45. package/dist/controller/controller.js +89 -116
  46. package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
  47. package/dist/controller/jobControl.js +17 -17
  48. package/dist/controller/resourceInventory.js +6 -6
  49. package/dist/controller/resourceInventoryLinux.js +38 -59
  50. package/dist/controller/resourceInventoryRpc.js +3 -3
  51. package/dist/controller/resourceInventoryWorker.js +1 -1
  52. package/dist/controller/runtime.js +46 -53
  53. package/dist/controller/runtimeEventInbox.js +23 -31
  54. package/dist/controller/runtimeEventProcessor.js +15 -15
  55. package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
  56. package/dist/controller/runtimeLaunchCoordinator.js +3 -3
  57. package/dist/controller/runtimeObservationHook.js +11 -8
  58. package/dist/controller/sessionNotify.js +11 -11
  59. package/dist/controller/structuredProviderObservation.js +89 -16
  60. package/dist/coordination/workMailbox.js +309 -579
  61. package/dist/coordination/workMailboxQueue.js +5 -6
  62. package/dist/core/controllerClient.js +1 -91
  63. package/dist/core/controllerServer.js +3 -6
  64. package/dist/doctor/doctor.js +51 -314
  65. package/dist/execution/candidateConvergence.js +3 -3
  66. package/dist/execution/executionGroup.js +32 -33
  67. package/dist/execution/executionHealth.js +36 -38
  68. package/dist/execution/resourceBroker.js +12 -12
  69. package/dist/executor/agentExecutor.js +30 -265
  70. package/dist/executor/effectiveLaunch.js +9 -19
  71. package/dist/executor/executorRegistry.js +43 -17
  72. package/dist/executor/fileRoleLaunchPlanner.js +56 -56
  73. package/dist/executor/launchPlan.js +3 -3
  74. package/dist/executor/workspacePreflightClassification.js +16 -16
  75. package/dist/grant/capabilityGrant.js +20 -25
  76. package/dist/input/inputRequest.js +12 -12
  77. package/dist/integration/changeSet.js +9 -13
  78. package/dist/integration/changeSetManifest.js +1 -1
  79. package/dist/integration/gitIntegrationService.js +2 -2
  80. package/dist/integration/integrationQueueService.js +5 -21
  81. package/dist/integration/overlapDiagnostics.js +2 -2
  82. package/dist/interaction/operatorPresentation.js +1 -1
  83. package/dist/job/jobRunner.js +1 -1
  84. package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
  85. package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
  86. package/dist/message/message.js +6 -6
  87. package/dist/observability/executionAudit.js +74 -86
  88. package/dist/observability/faultClassification.js +7 -24
  89. package/dist/observability/orchestrationMetrics.js +5 -5
  90. package/dist/observability/runtimeIdentity.js +34 -101
  91. package/dist/profile/agentProfile.js +1 -1
  92. package/dist/release/cliHomeReleaseFence.js +3 -3
  93. package/dist/release/releaseWorkflowEngine.js +6 -10
  94. package/dist/release/releaseWorkflowPorts.js +2 -2
  95. package/dist/release/workflowFileLock.js +1 -1
  96. package/dist/repository/checkoutSwap.js +1 -1
  97. package/dist/repository/gitWorkspace.js +0 -13
  98. package/dist/repository/project.js +1 -1
  99. package/dist/repository/projectMaintenanceLock.js +1 -2
  100. package/dist/repository/taskBaseFreshness.js +13 -13
  101. package/dist/repository/taskWorkspaceCoordinator.js +21 -25
  102. package/dist/repository/taskWorkspaceIdentity.js +8 -21
  103. package/dist/repository/taskWorkspacePreparer.js +63 -620
  104. package/dist/resources/autoResourceGc.js +3 -3
  105. package/dist/resources/liveReferences.js +1 -1
  106. package/dist/resources/resourceGc.js +1 -1
  107. package/dist/resources/sqliteResourceRegistry.js +1 -1
  108. package/dist/review/reviewDecision.js +7 -7
  109. package/dist/review/reviewFindingLedger.js +1 -1
  110. package/dist/review/reviewOutcomeClassifier.js +35 -50
  111. package/dist/review/reviewRound.js +14 -25
  112. package/dist/review/reviewerAvailability.js +4 -4
  113. package/dist/review/taskFinalReviewContractResolution.js +41 -0
  114. package/dist/role/role.js +6 -3
  115. package/dist/runtime/agentDriver.js +4 -0
  116. package/dist/runtime/agentHost.js +151 -36
  117. package/dist/runtime/builtinAgentDrivers.js +79 -2
  118. package/dist/runtime/codexAppServerRuntime.js +122 -0
  119. package/dist/runtime/continuationManager.js +3 -5
  120. package/dist/runtime/exactControlPlane.js +17 -42
  121. package/dist/runtime/firstProgressAdvisory.js +1 -1
  122. package/dist/runtime/index.js +2 -2
  123. package/dist/runtime/launchDiagnostics.js +2 -2
  124. package/dist/runtime/lifecycleReservation.js +4 -4
  125. package/dist/runtime/processExitObservation.js +1 -1
  126. package/dist/runtime/processExitOutbox.js +0 -32
  127. package/dist/runtime/promptEnvelope.js +9 -9
  128. package/dist/runtime/providerContinuation.js +2 -2
  129. package/dist/runtime/providerContinuationReconciliationService.js +2 -2
  130. package/dist/runtime/providerRuntimeIdentity.js +76 -24
  131. package/dist/runtime/recentTurnIds.js +38 -0
  132. package/dist/runtime/runtimeContinuationProjection.js +2 -2
  133. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  134. package/dist/runtime/runtimeObservation.js +58 -21
  135. package/dist/runtime/runtimeProjection.js +19 -27
  136. package/dist/runtime/sessionLaunchRequest.js +2 -2
  137. package/dist/runtime/structuredProviderHost.js +177 -12
  138. package/dist/runtime/tmuxAdapters.js +46 -11
  139. package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
  140. package/dist/scheduler/leaderWakeupProcessor.js +147 -445
  141. package/dist/scheduler/operatorEvent.js +4 -6
  142. package/dist/scheduler/resourceQueueProjection.js +71 -0
  143. package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
  144. package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
  145. package/dist/scheduler/taskExecutionProjection.js +99 -99
  146. package/dist/scheduler/taskObservabilityProjection.js +10 -10
  147. package/dist/scheduler/taskWake.js +4 -4
  148. package/dist/scheduler/wakeReason.js +6 -10
  149. package/dist/scheduler/wakeupQueue.js +0 -9
  150. package/dist/setup/setupCommand.js +2 -2
  151. package/dist/storage/currentTaskStore.js +46 -0
  152. package/dist/storage/persistenceWorker.js +1 -1
  153. package/dist/storage/sqliteSchema.js +81 -485
  154. package/dist/storage/sqliteStore.js +206 -365
  155. package/dist/storage/storageSchema.js +1 -15
  156. package/dist/storage/storageVersions.js +8 -9
  157. package/dist/storage/storeRpc.js +10 -34
  158. package/dist/storage/taskStore.js +63 -3415
  159. package/dist/storage/upgrade/recordVersions.js +55 -149
  160. package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
  161. package/dist/task/completionReadiness.js +5 -5
  162. package/dist/task/deliveryGuard.js +10 -10
  163. package/dist/task/nextAction.js +74 -77
  164. package/dist/task/task.js +2 -4
  165. package/dist/task/taskRecordReference.js +3 -3
  166. package/dist/task/taskRecordRetirement.js +1 -1
  167. package/dist/telemetry/sqliteTelemetryStore.js +53 -53
  168. package/dist/telemetry/telemetryConfig.js +14 -14
  169. package/dist/telemetry/telemetryWiring.js +8 -14
  170. package/dist/turn/turn.js +356 -0
  171. package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
  172. package/dist/verification/gateArtifactStore.js +2 -2
  173. package/dist/web/assets/client/app.js +1 -1
  174. package/dist/web/assets/client/components.js +29 -54
  175. package/dist/web/assets/client/i18n.js +17 -37
  176. package/dist/web/assets/client/view.js +37 -37
  177. package/dist/web/assets/shell.js +1 -1
  178. package/dist/web/assets/styles/cards.js +5 -5
  179. package/dist/web/assets/styles/widgets.js +1 -2
  180. package/dist/web/webSnapshot.js +65 -60
  181. package/dist/workItem/workItem.js +11 -11
  182. package/dist/workspace/workItemChangeSetManager.js +1 -1
  183. package/docs/task-local-identity.md +5 -5
  184. package/i18n/README.zh-CN.md +41 -54
  185. package/package.json +1 -1
  186. package/skills/yui-leader/SKILL.md +85 -83
  187. package/skills/yui-operator/SKILL.md +16 -16
  188. package/skills/yui-reviewer/SKILL.md +10 -10
  189. package/skills/yui-runtime/SKILL.md +17 -18
  190. package/skills/yui-worker/SKILL.md +16 -18
  191. package/dist/context/runContextContract.js +0 -162
  192. package/dist/executor/turnCompletion.js +0 -126
  193. package/dist/review/taskFinalReviewContractEvent.js +0 -1
  194. package/dist/review/taskFinalReviewContractRebind.js +0 -367
  195. package/dist/run/agentRun.js +0 -356
  196. package/dist/run/rejectedYieldAttempt.js +0 -221
  197. package/dist/run/runControlRequest.js +0 -50
  198. package/dist/run/yieldReceipt.js +0 -65
  199. package/dist/runtime/turnCompletion.js +0 -3
  200. package/dist/scheduler/actionability.js +0 -323
  201. package/dist/scheduler/activeRoleRunDelivery.js +0 -868
  202. package/dist/scheduler/activeTaskProgress.js +0 -126
  203. package/dist/storage/compatibleTaskStore.js +0 -248
  204. package/dist/storage/migration/baseline.js +0 -78
  205. package/dist/storage/migration/classifier.js +0 -51
  206. package/dist/storage/migration/compatibleCodec.js +0 -53
  207. package/dist/storage/migration/engine.js +0 -147
  208. package/dist/storage/migration/index.js +0 -33
  209. package/dist/storage/migration/planner.js +0 -154
  210. package/dist/storage/migration/productionRegistry.js +0 -3931
  211. package/dist/storage/migration/registry.js +0 -169
  212. package/dist/storage/migration/report.js +0 -54
  213. package/dist/storage/migration/types.js +0 -31
  214. package/dist/storage/upgrade/homeClassification.js +0 -353
  215. package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
  216. package/dist/storage/upgrade/migrationReceipt.js +0 -67
  217. package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
  218. package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
  219. package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
  220. package/dist/storage/upgrade/recordVersionScan.js +0 -176
  221. package/dist/storage/upgrade/sqliteFileSet.js +0 -50
  222. package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
  223. package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
  224. package/dist/storage/upgrade/sqliteStateMigration.js +0 -918
  225. package/dist/storage/upgrade/switchProgress.js +0 -80
  226. package/dist/storage/upgrade/upgradeReceipt.js +0 -161
  227. package/dist/storage/upgradeCoordination.js +0 -187
  228. package/dist/storage/upgradeFence.js +0 -366
  229. package/dist/telemetry/telemetryCompaction.js +0 -252
@@ -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
- }