@zq-silk/yui 0.15.11 → 0.16.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 (280) hide show
  1. package/ARCHITECTURE.md +11 -6
  2. package/ARCHITECTURE.zh-CN.md +8 -4
  3. package/README.md +13 -5
  4. package/dist/agentRun/agentRun.js +3 -0
  5. package/dist/artifacts/artifactCommitLock.js +16 -55
  6. package/dist/artifacts/taskArtifactRepository.js +3 -3
  7. package/dist/cli/agentConfigurationPicker.js +1 -1
  8. package/dist/cli/commandCatalog.js +92 -48
  9. package/dist/cli/completion.js +18 -18
  10. package/dist/cli/completionWizard.js +1 -1
  11. package/dist/cli/dynamicCompletion.js +1 -1
  12. package/dist/cli/interactionPolicy.js +11 -3
  13. package/dist/cli/invocationAuthority.js +64 -0
  14. package/dist/cli/managedDiagnostics.js +2 -2
  15. package/dist/cli/parseRepeatable.js +35 -0
  16. package/dist/cli/updatePorts.js +26 -5
  17. package/dist/cli.js +1303 -1235
  18. package/dist/commands/agentCommands.js +4 -4
  19. package/dist/commands/capabilityCommands.js +1 -1
  20. package/dist/commands/configCommands.js +6 -57
  21. package/dist/commands/configOverview.js +2 -2
  22. package/dist/commands/durableJobCommands.js +12 -6
  23. package/dist/commands/executionAuditCommands.js +10 -0
  24. package/dist/commands/globalRoleCommands.js +78 -29
  25. package/dist/commands/grantCommands.js +0 -3
  26. package/dist/commands/jobCommands.js +1 -4
  27. package/dist/commands/operatorCommands.js +3 -3
  28. package/dist/commands/projectCommands.js +45 -25
  29. package/dist/commands/resourcesCommands.js +10 -40
  30. package/dist/commands/roleConfiguration.js +2 -6
  31. package/dist/commands/taskActivationCommands.js +4 -8
  32. package/dist/commands/taskAgentCapabilities.js +9 -0
  33. package/dist/commands/taskCommandSupport.js +155 -0
  34. package/dist/commands/taskCommandTypes.js +1 -0
  35. package/dist/commands/taskCommands.js +355 -732
  36. package/dist/commands/taskCompletionGate.js +1 -1
  37. package/dist/commands/taskExecutionCommands.js +1 -1
  38. package/dist/commands/taskFactCommands.js +325 -0
  39. package/dist/commands/taskInputCommands.js +12 -42
  40. package/dist/commands/taskIntegrationCommands.js +20 -58
  41. package/dist/commands/taskNextActionCommand.js +7 -6
  42. package/dist/commands/taskPublicationAdoptCommand.js +127 -0
  43. package/dist/commands/taskPublicationCommands.js +12 -3
  44. package/dist/commands/taskPublicationVerifyCommand.js +24 -40
  45. package/dist/commands/taskRemoteDeliveryCommand.js +5 -86
  46. package/dist/commands/taskUpstreamCommands.js +19 -8
  47. package/dist/commands/workflowCommands.js +6 -1
  48. package/dist/completion/completionInstaller.js +26 -26
  49. package/dist/completion/completionState.js +26 -26
  50. package/dist/completion/fileCompletionManager.js +6 -11
  51. package/dist/config/configCatalog.js +0 -2
  52. package/dist/config/timeZone.js +14 -0
  53. package/dist/config/yuiConfig.js +0 -29
  54. package/dist/context/runContextPack.js +5 -3
  55. package/dist/context/taskCatalog.js +185 -0
  56. package/dist/context/taskContext.js +152 -151
  57. package/dist/context/wakeRunReferences.js +11 -0
  58. package/dist/controller/agentCapabilities.js +58 -0
  59. package/dist/controller/agentRuntimeObserver.js +6 -11
  60. package/dist/controller/clientRuntime.js +22 -14
  61. package/dist/controller/controller.js +20 -24
  62. package/dist/controller/fileSchedulerStoreAdapter.js +191 -225
  63. package/dist/controller/globalInputDelivery.js +13 -0
  64. package/dist/controller/jobClient.js +4 -4
  65. package/dist/controller/jobControl.js +60 -25
  66. package/dist/controller/jobSupervisor.js +4 -4
  67. package/dist/controller/providerRetryAdmission.js +100 -0
  68. package/dist/controller/providerRetryDelivery.js +218 -0
  69. package/dist/controller/runtime.js +85 -43
  70. package/dist/controller/runtimeEventProcessor.js +0 -5
  71. package/dist/controller/sessionOwnerReconciliation.js +5 -0
  72. package/dist/controller/taskAgentError.js +35 -0
  73. package/dist/coordination/workMailboxQueue.js +2 -24
  74. package/dist/core/controllerClient.js +2 -2
  75. package/dist/core/fileLockOwner.js +74 -0
  76. package/dist/decision/decision.js +17 -0
  77. package/dist/doctor/doctor.js +18 -9
  78. package/dist/event/taskEvent.js +12 -0
  79. package/dist/execution/workItemExecutionProjection.js +2 -2
  80. package/dist/executor/agentCapabilityConfig.js +43 -0
  81. package/dist/executor/agentConfigurationCatalog.js +49 -11
  82. package/dist/executor/agentExecutor.js +5 -8
  83. package/dist/executor/fileRoleLaunchPlanner.js +11 -53
  84. package/dist/executor/taskAgentCapabilities.js +64 -0
  85. package/dist/integration/deliveryObligation.js +1 -69
  86. package/dist/integration/gitIntegrationService.js +79 -90
  87. package/dist/integration/integrationAttempt.js +3 -14
  88. package/dist/integration/integrationSourceApplication.js +4 -12
  89. package/dist/integration/manifestTags.js +2 -2
  90. package/dist/job/durableJob.js +4 -25
  91. package/dist/job/jobAssignmentScope.js +22 -0
  92. package/dist/job/jobOperation.js +16 -0
  93. package/dist/job/jobRunner.js +2 -1
  94. package/dist/job/stepDirectory.js +15 -0
  95. package/dist/kernel/builtinCapabilities.js +15 -11
  96. package/dist/kernel/kernelPorts.js +1 -17
  97. package/dist/lifecycle/exactRunTerminalization.js +5 -10
  98. package/dist/message/globalProviderRetry.js +15 -0
  99. package/dist/message/inputControlResolution.js +3 -4
  100. package/dist/message/message.js +17 -20
  101. package/dist/message/messageContinuation.js +1 -1
  102. package/dist/milestone/milestone.js +11 -0
  103. package/dist/observability/executionAudit.js +19 -0
  104. package/dist/observability/orchestrationMetrics.js +24 -1
  105. package/dist/observability/runtimeIdentity.js +1 -17
  106. package/dist/output/agentConfigurationPresentation.js +2 -0
  107. package/dist/output/timePresentation.js +1 -14
  108. package/dist/plugins/pluginService.js +12 -4
  109. package/dist/release/releaseWorkflowPorts.js +45 -96
  110. package/dist/release/runtimeRelease.js +9 -15
  111. package/dist/repository/gitWorkspace.js +371 -105
  112. package/dist/repository/projectMaintenanceLock.js +98 -82
  113. package/dist/repository/taskBaseFreshness.js +1 -1
  114. package/dist/repository/taskWorkspaceCoordinator.js +82 -144
  115. package/dist/repository/taskWorkspacePreparer.js +113 -47
  116. package/dist/repository/workspaceCleanupInspection.js +187 -0
  117. package/dist/resources/autoResourceGc.js +4 -77
  118. package/dist/resources/liveReferences.js +7 -54
  119. package/dist/resources/resourceDiscovery.js +5 -118
  120. package/dist/resources/resourceGc.js +233 -181
  121. package/dist/resources/resourceRegistrar.js +5 -4
  122. package/dist/resources/resourceRegistry.js +3 -37
  123. package/dist/resources/resourceRegistryStore.js +13 -36
  124. package/dist/resources/sqliteResourceRegistry.js +43 -26
  125. package/dist/review/deltaRecheck.js +1 -1
  126. package/dist/review/reviewAcceptance.js +1 -1
  127. package/dist/review/reviewDecision.js +1 -1
  128. package/dist/review/reviewRound.js +8 -7
  129. package/dist/review/taskFinalReviewContractResolution.js +1 -1
  130. package/dist/runtime/acpProtocol.js +4 -51
  131. package/dist/runtime/acpSession.js +10 -75
  132. package/dist/runtime/acpSessionConfiguration.js +1 -8
  133. package/dist/runtime/agentEndpoint.js +3 -2
  134. package/dist/runtime/agentError.js +5 -3
  135. package/dist/runtime/agentFailureContext.js +43 -0
  136. package/dist/runtime/agentHost.js +42 -25
  137. package/dist/runtime/builtinAgentErrorMappers.js +91 -0
  138. package/dist/runtime/codexAppServerRuntime.js +34 -3
  139. package/dist/runtime/codexInteractiveHost.js +2 -2
  140. package/dist/runtime/index.js +0 -1
  141. package/dist/runtime/managedCaller.js +21 -1
  142. package/dist/runtime/providerControl.js +5 -1
  143. package/dist/runtime/providerErrors.js +38 -0
  144. package/dist/runtime/providerRetry.js +198 -0
  145. package/dist/runtime/providerRuntimeIdentity.js +28 -2
  146. package/dist/runtime/runtimeObservation.js +0 -5
  147. package/dist/runtime/runtimeSessionCandidate.js +2 -3
  148. package/dist/runtime/sessionOwnerIdentity.js +1 -1
  149. package/dist/runtime/sessionTokenMetrics.js +15 -5
  150. package/dist/runtime/structuredProviderHost.js +10 -43
  151. package/dist/runtime/taskUsageMetrics.js +275 -0
  152. package/dist/runtime/tmuxAdapters.js +6 -8
  153. package/dist/scheduler/activeRoleRunDelivery.js +19 -7
  154. package/dist/scheduler/leaderWakeupProcessor.js +24 -6
  155. package/dist/scheduler/operatorEvent.js +12 -20
  156. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  157. package/dist/scheduler/ports.js +5 -8
  158. package/dist/scheduler/roleRunLiveness.js +4 -4
  159. package/dist/scheduler/roleRunStall.js +16 -23
  160. package/dist/scheduler/taskExecutionProjection.js +49 -36
  161. package/dist/scheduler/taskObservabilityProjection.js +6 -45
  162. package/dist/scheduler/taskWake.js +5 -10
  163. package/dist/scheduler/wakeReason.js +2 -0
  164. package/dist/scheduler/wakeupQueue.js +2 -4
  165. package/dist/setup/setupCommand.js +1 -1
  166. package/dist/storage/contextRecords.js +106 -0
  167. package/dist/storage/currentTaskStore.js +1 -1
  168. package/dist/storage/homeLayout.js +13 -17
  169. package/dist/storage/migrations/agentFailureContext.js +22 -0
  170. package/dist/storage/migrations/currentInputContract.js +86 -0
  171. package/dist/storage/migrations/currentRuntimeContract.js +228 -0
  172. package/dist/storage/migrations/historicalVerificationPlan.js +35 -0
  173. package/dist/storage/migrations/integrationContinuation.js +5 -4
  174. package/dist/storage/migrations/narrowAgentFailureContext.js +65 -0
  175. package/dist/storage/migrations/notificationOnlyWakes.js +74 -0
  176. package/dist/storage/migrations/verificationPlanV1.js +162 -0
  177. package/dist/storage/migrations/verificationPolicy.js +74 -0
  178. package/dist/storage/migrations/workItemHistory.js +46 -0
  179. package/dist/storage/persistenceWorker.js +12 -4
  180. package/dist/storage/recordValidation.js +87 -0
  181. package/dist/storage/sqliteSchema.js +173 -1
  182. package/dist/storage/sqliteStore.js +172 -161
  183. package/dist/storage/storageSchema.js +2 -14
  184. package/dist/storage/storageVersions.js +1 -1
  185. package/dist/storage/storeRpc.js +16 -7
  186. package/dist/storage/taskCatalog.js +123 -0
  187. package/dist/storage/taskStore.js +5 -7
  188. package/dist/storage/upgrade/upgradeOrchestrator.js +25 -37
  189. package/dist/task/archiveDiagnostics.js +1 -0
  190. package/dist/task/archivePreflight.js +124 -0
  191. package/dist/task/completionReadiness.js +5 -24
  192. package/dist/task/draftPlan.js +0 -53
  193. package/dist/task/nextAction.js +7 -13
  194. package/dist/task/publicationAdoption.js +56 -0
  195. package/dist/task/publicationReference.js +10 -0
  196. package/dist/task/remoteDelivery.js +31 -16
  197. package/dist/task/remoteDeliveryService.js +89 -0
  198. package/dist/task/taskActivation.js +2 -25
  199. package/dist/task/taskActivationService.js +0 -2
  200. package/dist/task/taskRecordReference.js +0 -1
  201. package/dist/task/taskSubmission.js +3 -14
  202. package/dist/telemetry/sqliteTelemetryBatch.js +29 -0
  203. package/dist/telemetry/sqliteTelemetryStore.js +49 -49
  204. package/dist/telemetry/telemetryWiring.js +4 -3
  205. package/dist/tmux/tmuxManager.js +29 -20
  206. package/dist/verification/gateArtifact.js +15 -24
  207. package/dist/verification/gateArtifactStore.js +14 -7
  208. package/dist/verification/verificationGateService.js +29 -88
  209. package/dist/verification/verificationPlan.js +27 -72
  210. package/dist/web/assets/client/app.js +92 -17
  211. package/dist/web/assets/client/components.js +55 -13
  212. package/dist/web/assets/client/i18n.js +72 -4
  213. package/dist/web/assets/client/taskSurface.js +6 -5
  214. package/dist/web/assets/client/view.js +35 -7
  215. package/dist/web/assets/shell.js +6 -0
  216. package/dist/web/assets/styles/layout.js +7 -0
  217. package/dist/web/webServer.js +12 -3
  218. package/dist/web/webSnapshot.js +14 -85
  219. package/dist/web/webTaskSurface.js +17 -46
  220. package/dist/workItem/workItem.js +1 -12
  221. package/dist/workspace/cleanupInspection.js +63 -0
  222. package/dist/workspace/workItemChangeSetManager.js +110 -50
  223. package/docs/agent-result-consumption.md +4 -0
  224. package/docs/agent-result-consumption.zh-CN.md +3 -0
  225. package/docs/agent-runtime-drivers.md +7 -0
  226. package/docs/agent-runtime-drivers.zh-CN.md +5 -0
  227. package/docs/architecture/README.md +2 -0
  228. package/docs/architecture/README.zh-CN.md +3 -1
  229. package/docs/architecture/capabilities-and-resources.md +42 -5
  230. package/docs/architecture/capabilities-and-resources.zh-CN.md +33 -3
  231. package/docs/managed-turn-and-session-runtime.md +121 -1
  232. package/docs/managed-turn-and-session-runtime.zh-CN.md +96 -2
  233. package/docs/observability/README.md +62 -0
  234. package/docs/observability/README.zh-CN.md +47 -0
  235. package/docs/plugin-sdk.md +4 -2
  236. package/docs/project-refresh.md +77 -0
  237. package/docs/project-refresh.zh-CN.md +59 -0
  238. package/docs/provider-retry.md +70 -0
  239. package/docs/provider-runtime.md +3 -1
  240. package/docs/provider-runtime.zh-CN.md +4 -2
  241. package/docs/release-workflow.md +190 -7
  242. package/docs/release-workflow.zh-CN.md +139 -5
  243. package/docs/roles-and-configuration.md +29 -0
  244. package/docs/roles-and-configuration.zh-CN.md +21 -0
  245. package/docs/sqlite-control-plane-design.md +16 -3
  246. package/docs/sqlite-control-plane-design.zh-CN.md +13 -2
  247. package/docs/task-dag-semantics.md +3 -3
  248. package/docs/task-dag-semantics.zh-CN.md +2 -2
  249. package/docs/task-delivery.md +223 -17
  250. package/docs/task-delivery.zh-CN.md +171 -14
  251. package/docs/task-discovery.md +101 -0
  252. package/docs/task-discovery.zh-CN.md +85 -0
  253. package/docs/testing/verification-levels.md +161 -9
  254. package/docs/testing/verification-levels.zh-CN.md +116 -9
  255. package/i18n/README.zh-CN.md +13 -7
  256. package/package.json +1 -1
  257. package/skills/yui-leader/SKILL.md +5 -0
  258. package/skills/yui-leader/references/execution.md +3 -2
  259. package/skills/yui-leader/references/integration.md +9 -5
  260. package/skills/yui-leader/references/planning.md +9 -3
  261. package/skills/yui-operator/SKILL.md +24 -8
  262. package/skills/yui-reviewer/SKILL.md +4 -0
  263. package/skills/yui-runtime/SKILL.md +17 -2
  264. package/skills/yui-runtime/references/publication.md +26 -4
  265. package/skills/yui-runtime/references/recovery.md +71 -0
  266. package/dist/agent/agentRegistry.js +0 -10
  267. package/dist/agentRun/runIdentity.js +0 -22
  268. package/dist/commands/deliveryGuardPreflight.js +0 -30
  269. package/dist/commands/taskIntegrationQueueCommands.js +0 -226
  270. package/dist/commands/taskOverviewCommand.js +0 -376
  271. package/dist/completion/completionWizard.js +0 -125
  272. package/dist/context/dispatchContext.js +0 -110
  273. package/dist/context/wakeNotification.js +0 -144
  274. package/dist/integration/integrationCheckEvidenceReuse.js +0 -53
  275. package/dist/integration/integrationQueueEntry.js +0 -191
  276. package/dist/integration/integrationQueueService.js +0 -810
  277. package/dist/release/fakeReleasePorts.js +0 -55
  278. package/dist/runtime/sessionOwnerRegistry.js +0 -137
  279. package/dist/task/deliveryGuard.js +0 -226
  280. /package/dist/{commands/taskActor.js → task/taskAuthority.js} +0 -0
@@ -1,144 +0,0 @@
1
- import { renderWakeReason } from "../scheduler/wakeReason.js";
2
- import { operationalTaskRecords } from "../task/taskRecordRetirement.js";
3
- /**
4
- * Issue 04 (context token budget) — long-term design:
5
- *
6
- * A Leader wake is a NOTIFICATION, not a context dump. The wake envelope
7
- * carries only what the Agent needs for immediate orientation: the wake id,
8
- * aggregated reason tags, delta window, and a bounded list of active frozen
9
- * Task Reviews. The Agent reads delta content on demand with
10
- * `yui task wake show <wake-id>` and the full projection with
11
- * `yui task context <task>`.
12
- *
13
- * The envelope is mode-agnostic: fresh Sessions and resumed Sessions
14
- * receive the same minimal text. The native Session is a disposable cache of
15
- * working context; Yui's durable Task records (including the wake ledger) are
16
- * the checkpoint.
17
- */
18
- /** Structural guardrail: the envelope stays far below a normal model context window. */
19
- export const WAKE_ENVELOPE_HARD_BYTES = 2_000;
20
- /** Maximum reason tags rendered before elision to a count. */
21
- const REASON_DISPLAY_LIMIT = 6;
22
- export function buildTaskWakeEnvelope(reader, request) {
23
- const task = reader.getTask(request.taskId);
24
- if (task === null)
25
- throw new Error(`Task not found: ${request.taskId}.`);
26
- if (request.reasons.length === 0) {
27
- throw new Error(`Wake envelope ${request.wakeId} must carry at least one reason.`);
28
- }
29
- const fromTime = Date.parse(request.fromCursor);
30
- const events = reader.listEvents(request.taskId);
31
- const deltaEvents = events.filter((record) => Date.parse(record.createdAt) > fromTime);
32
- const runs = operationalTaskRecords(reader.listRuns(request.taskId), events, "run");
33
- const referencedRunIds = referencedWakeRunIds(runs, events, deltaEvents);
34
- const changedRunIds = new Set([
35
- ...runs
36
- .filter((record) => Date.parse(record.createdAt) > fromTime)
37
- .map(({ id }) => id),
38
- ...referencedRunIds
39
- ]);
40
- const counts = {
41
- events: deltaEvents.length,
42
- messages: operationalTaskRecords(reader.listMessages(request.taskId), events, "message")
43
- .filter((record) => Date.parse(record.createdAt) > fromTime).length,
44
- runs: changedRunIds.size
45
- };
46
- const activeReviews = reader.listReviewRounds(request.taskId).filter((round) => ((round.scope ?? "work-item") === "task"
47
- && (round.status === "pending" || round.status === "running")));
48
- const renderReviewOrientation = (limit) => activeReviews.slice(0, limit).map((round) => {
49
- const projects = round.taskCandidate?.projects ?? [];
50
- const heads = projects.slice(0, 2).map(({ projectId, commit }) => (`${projectId}@${commit.slice(0, 12)}`)).join("+");
51
- return `${round.id}/${round.reviewerRoleName}`
52
- + `/${round.deltaRecheck === undefined ? "full" : "delta"}`
53
- + `[${round.status}]`
54
- + `@${heads || round.reviewBaseCommit.slice(0, 12)}`
55
- + `${projects.length > 2 ? `+${projects.length - 2}` : ""}`;
56
- }).join(", ");
57
- const render = (reasonLimit, resultRunLimit, reviewLimit) => {
58
- const reviewOrientation = renderReviewOrientation(reviewLimit);
59
- return [
60
- `Wake: ${request.wakeId} — delta since ${request.fromCursor}`,
61
- ` Reasons: ${renderReasons(request.reasons, reasonLimit)}`,
62
- ` Changed: ${counts.events} events, ${counts.messages} messages, ${counts.runs} AgentRuns`
63
- + ` → yui task wake show ${request.taskId} ${request.wakeId}`,
64
- ` Result AgentRuns: ${renderResultRuns(request.taskId, referencedRunIds, resultRunLimit)}`,
65
- ` Active Task Reviews: ${activeReviews.length === 0
66
- ? "none"
67
- : reviewLimit === 0
68
- ? `${activeReviews.length} → yui task context ${request.taskId}`
69
- : `${reviewOrientation}${activeReviews.length > reviewLimit
70
- ? `, … (+${activeReviews.length - reviewLimit})`
71
- : ""}`}`,
72
- `Full context: yui task context ${request.taskId}`
73
- ].join("\n");
74
- };
75
- let reasonLimit = Math.min(REASON_DISPLAY_LIMIT, request.reasons.length);
76
- let resultRunLimit = Math.min(4, referencedRunIds.length);
77
- let reviewLimit = Math.min(3, activeReviews.length);
78
- let body = render(reasonLimit, resultRunLimit, reviewLimit);
79
- while (byteLength(body) + 1 > WAKE_ENVELOPE_HARD_BYTES) {
80
- if (resultRunLimit > 0)
81
- resultRunLimit -= 1;
82
- else if (reasonLimit > 0)
83
- reasonLimit -= 1;
84
- else if (reviewLimit > 0)
85
- reviewLimit -= 1;
86
- else
87
- break;
88
- body = render(reasonLimit, resultRunLimit, reviewLimit);
89
- }
90
- if (byteLength(body) + 1 > WAKE_ENVELOPE_HARD_BYTES) {
91
- body = fitUtf8([
92
- `Wake: ${request.wakeId}`,
93
- `Inspect: yui task wake show ${request.taskId} ${request.wakeId}`,
94
- `Full context: yui task context ${request.taskId}`
95
- ].join("\n"), WAKE_ENVELOPE_HARD_BYTES - 1);
96
- }
97
- const totalBytes = byteLength(body) + 1;
98
- return Object.freeze({
99
- taskId: request.taskId,
100
- wakeId: request.wakeId,
101
- fromCursor: request.fromCursor,
102
- referencedRunIds: Object.freeze(referencedRunIds),
103
- totalBytes,
104
- text: `${body}\n`
105
- });
106
- }
107
- export function referencedWakeRunIds(runs, allEvents, terminalEvents) {
108
- const turnsById = new Map(operationalTaskRecords(runs, allEvents, "run").map((run) => [run.id, run]));
109
- return [...new Set(terminalEvents.flatMap((event) => {
110
- if (!["run.completed", "run.failed", "run.cancelled"].includes(event.type))
111
- return [];
112
- const runId = event.payload.runId;
113
- return runId !== undefined && turnsById.has(runId) ? [runId] : [];
114
- }))];
115
- }
116
- function renderReasons(reasons, limit) {
117
- if (limit === 0)
118
- return `${reasons.length} reason tags`;
119
- const selected = reasons.slice(0, limit);
120
- const elided = reasons.length - selected.length;
121
- const rendered = selected.map(renderWakeReason).join(", ");
122
- return elided === 0 ? rendered : `${rendered}, … (+${elided} more)`;
123
- }
124
- function renderResultRuns(taskId, runIds, limit) {
125
- if (runIds.length === 0)
126
- return "none";
127
- if (limit === 0)
128
- return `${runIds.length} → inspect the wake delta`;
129
- return `${runIds.slice(0, limit)
130
- .map((runId) => `${runId} → yui task run show ${taskId}/${runId}`)
131
- .join(", ")}${runIds.length > limit ? `, … (+${runIds.length - limit})` : ""}`;
132
- }
133
- function fitUtf8(value, maxBytes) {
134
- let fitted = "";
135
- for (const character of value) {
136
- if (byteLength(fitted) + byteLength(character) > maxBytes)
137
- break;
138
- fitted += character;
139
- }
140
- return fitted;
141
- }
142
- function byteLength(value) {
143
- return Buffer.byteLength(value, "utf8");
144
- }
@@ -1,53 +0,0 @@
1
- /** Internal, Controller-derived release fence carried by Integration jobs. */
2
- export const INTEGRATION_RUNTIME_RELEASE_ENV = "YUI_INTEGRATION_RUNTIME_RELEASE_ID";
3
- /**
4
- * Find exact reusable evidence without creating cache state. Every identity
5
- * field is read from the existing IntegrationAttempt and DurableJob records.
6
- */
7
- export function findReusableIntegrationCheckEvidence(input) {
8
- const attempts = [...input.attempts]
9
- .filter((attempt) => (attempt.taskId === input.taskId
10
- && attempt.id !== input.currentAttemptId
11
- && attempt.projectId === input.projectId
12
- && sameOrderedText(attempt.checkCommands, input.checkCommands)))
13
- .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
14
- for (const attempt of attempts) {
15
- if (attempt.jobId === undefined)
16
- continue;
17
- const job = input.jobs.find((candidate) => (candidate.id === attempt.jobId
18
- && candidate.taskId === input.taskId
19
- && candidate.owner.kind === "integration-attempt"
20
- && candidate.owner.integrationAttemptId === attempt.id));
21
- const resultSteps = job?.result?.steps ?? [];
22
- const logPaths = resultSteps.map((step) => (input.logPathFor?.(job, step.logPath) ?? step.logPath));
23
- if (job === undefined
24
- || job.projectId !== input.projectId
25
- || job.head !== input.candidateCommit
26
- || job.status !== "succeeded"
27
- || job.result?.outcome !== "succeeded"
28
- || job.env[INTEGRATION_RUNTIME_RELEASE_ENV] !== input.runtimeReleaseId
29
- || job.steps.length !== input.checkCommands.length
30
- || job.steps.some((step, index) => (step.name !== `check-${index + 1}`
31
- || step.command !== input.checkCommands[index]))
32
- || resultSteps.length !== input.checkCommands.length
33
- || resultSteps.some((step, index) => (step.name !== `check-${index + 1}`
34
- || step.exitCode !== 0
35
- || step.signal !== null
36
- || step.timedOut
37
- || step.head !== input.candidateCommit
38
- || (input.logExists !== undefined && !input.logExists(logPaths[index]))))) {
39
- continue;
40
- }
41
- const checks = resultSteps.map((step, index) => ({
42
- name: input.checkCommands[index],
43
- outcome: "passed",
44
- details: `Reused successful check evidence from ${attempt.id}/${job.id}.`,
45
- logPath: logPaths[index]
46
- }));
47
- return Object.freeze({ sourceAttempt: attempt, sourceJob: job, checks });
48
- }
49
- return null;
50
- }
51
- function sameOrderedText(left, right) {
52
- return left.length === right.length && left.every((value, index) => value === right[index]);
53
- }
@@ -1,191 +0,0 @@
1
- import { normalizedUniqueIdentities, normalizedUniqueText, requireIdentity, requireText, requireTimestamp } from "../domain/validation.js";
2
- import { validateTaskRecordReference } from "../task/taskRecordReference.js";
3
- export function createIntegrationQueueEntry(input, now) {
4
- const timestamp = now.toISOString();
5
- return validateIntegrationQueueEntry({
6
- schemaVersion: 1,
7
- id: input.id,
8
- taskId: input.taskId,
9
- projectId: input.projectId,
10
- changeSetId: input.changeSetId,
11
- targetRef: input.targetRef,
12
- status: "queued",
13
- checkCommands: normalizedUniqueText(input.checkCommands ?? [], "Integration queue check command"),
14
- evidenceRefs: normalizedUniqueText(input.evidenceRefs ?? [], "Integration queue evidence"),
15
- createdAt: timestamp,
16
- updatedAt: timestamp
17
- });
18
- }
19
- /**
20
- * An entry whose ChangeSet is already represented on the target (an ancestor
21
- * or a same-tree commit) converges directly to committed with its proof. The
22
- * entry still names the committed IntegrationAttempt that recorded the
23
- * convergence, so every acceptance and provenance consumer reads one
24
- * integration authority.
25
- */
26
- export function createConvergedIntegrationQueueEntry(input, now) {
27
- const timestamp = now.toISOString();
28
- return validateIntegrationQueueEntry({
29
- schemaVersion: 1,
30
- id: input.id,
31
- taskId: input.taskId,
32
- projectId: input.projectId,
33
- changeSetId: input.changeSetId,
34
- targetRef: input.targetRef,
35
- status: "committed",
36
- checkCommands: [],
37
- targetBefore: input.targetHead,
38
- targetAfter: input.targetHead,
39
- evidenceRefs: [input.proof],
40
- ...(input.integrationAttemptId === undefined
41
- ? {}
42
- : { integrationAttemptId: input.integrationAttemptId }),
43
- createdAt: timestamp,
44
- updatedAt: timestamp,
45
- endedAt: timestamp
46
- });
47
- }
48
- export function markIntegrationQueueRunning(entry, targetBefore, now) {
49
- validateIntegrationQueueEntry(entry);
50
- if (!["queued", "conflicted"].includes(entry.status)) {
51
- throw new Error(`Integration queue entry cannot run from ${entry.status}: ${entry.id}.`);
52
- }
53
- const { conflictSummary: _previousConflict, ...rest } = entry;
54
- return validateIntegrationQueueEntry({
55
- ...rest,
56
- status: "running",
57
- targetBefore,
58
- updatedAt: now.toISOString()
59
- });
60
- }
61
- export function recordIntegrationQueueAttempt(entry, integrationAttemptId, now) {
62
- validateIntegrationQueueEntry(entry);
63
- if (entry.status !== "running") {
64
- throw new Error(`Integration queue entry is not running: ${entry.id}/${entry.status}.`);
65
- }
66
- return validateIntegrationQueueEntry({
67
- ...entry,
68
- integrationAttemptId,
69
- updatedAt: now.toISOString()
70
- });
71
- }
72
- export function markIntegrationQueueBlocked(entry, conflictSummary, now) {
73
- validateIntegrationQueueEntry(entry);
74
- if (entry.status !== "running") {
75
- throw new Error(`Integration queue entry is not running: ${entry.id}/${entry.status}.`);
76
- }
77
- return validateIntegrationQueueEntry({
78
- ...entry,
79
- status: "conflicted",
80
- conflictSummary: requireText(conflictSummary, "Integration queue conflict summary"),
81
- updatedAt: now.toISOString()
82
- });
83
- }
84
- export function markIntegrationQueueCommitted(entry, targetAfter, now) {
85
- validateIntegrationQueueEntry(entry);
86
- if (entry.status !== "running" && entry.status !== "conflicted") {
87
- throw new Error(`Integration queue entry cannot commit from ${entry.status}: ${entry.id}.`);
88
- }
89
- const timestamp = now.toISOString();
90
- return validateIntegrationQueueEntry({
91
- ...entry,
92
- status: "committed",
93
- targetAfter,
94
- updatedAt: timestamp,
95
- endedAt: timestamp
96
- });
97
- }
98
- /** A conflicted entry is manually retried after its underlying issue was fixed. */
99
- export function markIntegrationQueueRequeued(entry, now) {
100
- validateIntegrationQueueEntry(entry);
101
- if (entry.status !== "conflicted") {
102
- throw new Error(`Integration queue entry cannot requeue from ${entry.status}: ${entry.id}.`);
103
- }
104
- return validateIntegrationQueueEntry({
105
- ...entry,
106
- status: "queued",
107
- updatedAt: now.toISOString()
108
- });
109
- }
110
- export function recordIntegrationQueueAffectedPaths(entry, affectedPaths, now) {
111
- validateIntegrationQueueEntry(entry);
112
- if (entry.status !== "queued") {
113
- throw new Error(`Integration queue entry cannot recompute overlap from ${entry.status}: ${entry.id}.`);
114
- }
115
- const previous = new Set(entry.affectedPaths ?? []);
116
- const merged = [...new Set([...previous, ...affectedPaths])].sort();
117
- return validateIntegrationQueueEntry({
118
- ...entry,
119
- affectedPaths: merged,
120
- updatedAt: now.toISOString()
121
- });
122
- }
123
- export function markIntegrationQueueSuperseded(entry, reason, now) {
124
- validateIntegrationQueueEntry(entry);
125
- if (!["queued", "conflicted"].includes(entry.status)) {
126
- throw new Error(`Integration queue entry cannot be superseded from ${entry.status}: ${entry.id}.`);
127
- }
128
- const timestamp = now.toISOString();
129
- return validateIntegrationQueueEntry({
130
- ...entry,
131
- status: "superseded",
132
- supersedeReason: requireText(reason, "Integration queue supersede reason"),
133
- updatedAt: timestamp,
134
- endedAt: timestamp
135
- });
136
- }
137
- export function validateIntegrationQueueEntry(entry) {
138
- if (entry.schemaVersion !== 1) {
139
- throw new Error("IntegrationQueueEntry must use schemaVersion 1.");
140
- }
141
- validateTaskRecordReference({ taskId: entry.taskId, localId: entry.id }, "integrationQueue");
142
- validateTaskRecordReference({ taskId: entry.taskId, localId: entry.changeSetId }, "changeSet");
143
- requireIdentity(entry.projectId, "Project id");
144
- requireText(entry.targetRef, "Integration queue target ref");
145
- normalizedUniqueText(entry.checkCommands, "Integration queue check command");
146
- normalizedUniqueText(entry.evidenceRefs, "Integration queue evidence");
147
- if (![
148
- "queued",
149
- "running",
150
- "conflicted",
151
- "committed",
152
- "superseded"
153
- ].includes(entry.status)) {
154
- throw new Error(`Integration queue status is invalid: ${String(entry.status)}.`);
155
- }
156
- if (entry.targetBefore !== undefined)
157
- requireCommit(entry.targetBefore, "Integration queue targetBefore");
158
- if (entry.targetAfter !== undefined)
159
- requireCommit(entry.targetAfter, "Integration queue targetAfter");
160
- if (entry.integrationAttemptId !== undefined) {
161
- normalizedUniqueIdentities([entry.integrationAttemptId], "Integration attempt id");
162
- }
163
- if (entry.conflictSummary !== undefined) {
164
- requireText(entry.conflictSummary, "Integration queue conflict summary");
165
- }
166
- if (entry.affectedPaths !== undefined) {
167
- normalizedUniqueText(entry.affectedPaths, "Integration queue affected path");
168
- }
169
- if (entry.supersedeReason !== undefined) {
170
- requireText(entry.supersedeReason, "Integration queue supersede reason");
171
- }
172
- requireTimestamp(entry.createdAt, "Integration queue entry createdAt");
173
- requireTimestamp(entry.updatedAt, "Integration queue entry updatedAt");
174
- if (["committed", "superseded"].includes(entry.status)) {
175
- requireTimestamp(entry.endedAt ?? "", "Integration queue entry endedAt");
176
- }
177
- if (entry.status === "committed") {
178
- requireCommit(entry.targetAfter ?? "", "Integration queue targetAfter");
179
- }
180
- if (entry.status === "running") {
181
- requireCommit(entry.targetBefore ?? "", "Integration queue targetBefore");
182
- }
183
- return entry;
184
- }
185
- function requireCommit(value, label) {
186
- const normalized = requireText(value, label).toLowerCase();
187
- if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u.test(normalized)) {
188
- throw new Error(`${label} is invalid.`);
189
- }
190
- return normalized;
191
- }