@zq-silk/yui 0.5.3 → 0.6.1

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 (157) hide show
  1. package/README.md +5 -5
  2. package/dist/agent/managedRuntimeEnvironment.js +2 -1
  3. package/dist/cli/agentConfigurationPicker.js +1 -1
  4. package/dist/cli/commandCatalog.js +251 -13
  5. package/dist/cli/updateOrchestrator.js +8 -0
  6. package/dist/cli/updatePorts.js +76 -22
  7. package/dist/cli.js +264 -20
  8. package/dist/commands/configCommands.js +83 -9
  9. package/dist/commands/controllerCommands.js +103 -0
  10. package/dist/commands/deliveryGuardPreflight.js +35 -0
  11. package/dist/commands/durableJobCommands.js +231 -0
  12. package/dist/commands/executionAuditCommands.js +193 -0
  13. package/dist/commands/grantCommands.js +374 -0
  14. package/dist/commands/projectCommands.js +119 -81
  15. package/dist/commands/releaseCommands.js +444 -0
  16. package/dist/commands/resourcesCommands.js +274 -0
  17. package/dist/commands/sessionCommands.js +104 -0
  18. package/dist/commands/taskActor.js +117 -0
  19. package/dist/commands/taskChangeSetCommands.js +60 -0
  20. package/dist/commands/taskCommands.js +610 -201
  21. package/dist/commands/taskCompletionGate.js +78 -1
  22. package/dist/commands/taskContextCommand.js +24 -6
  23. package/dist/commands/taskInputCommands.js +1 -1
  24. package/dist/commands/taskIntegrationCommands.js +136 -33
  25. package/dist/commands/taskIntegrationQueueCommands.js +228 -0
  26. package/dist/commands/taskNextActionCommand.js +85 -0
  27. package/dist/commands/taskOverlapCommands.js +120 -0
  28. package/dist/commands/taskOverviewCommand.js +36 -8
  29. package/dist/commands/telemetryCommands.js +330 -0
  30. package/dist/commands/workflowCommands.js +415 -0
  31. package/dist/config/yuiConfig.js +60 -0
  32. package/dist/controller/clientRuntime.js +42 -1
  33. package/dist/controller/controller.js +413 -61
  34. package/dist/controller/controllerMain.js +25 -2
  35. package/dist/controller/domainIdentity.js +16 -8
  36. package/dist/controller/ephemeralResourceReaper.js +2 -1
  37. package/dist/controller/fileSchedulerStoreAdapter.js +423 -31
  38. package/dist/controller/handoverCandidate.js +168 -0
  39. package/dist/controller/jobClient.js +102 -0
  40. package/dist/controller/jobControl.js +613 -0
  41. package/dist/controller/jobSupervisor.js +498 -0
  42. package/dist/controller/providerHookRunFence.js +34 -5
  43. package/dist/controller/resourceCleanupLinux.js +18 -9
  44. package/dist/controller/resourceInventoryLinux.js +90 -39
  45. package/dist/controller/resourceInventoryRpc.js +85 -0
  46. package/dist/controller/resourceInventoryWorker.js +50 -0
  47. package/dist/controller/runtime.js +238 -22
  48. package/dist/controller/runtimeEventInbox.js +234 -57
  49. package/dist/controller/runtimeEventProcessor.js +549 -42
  50. package/dist/controller/sessionOwnerReconciliation.js +321 -0
  51. package/dist/core/boundedRpc.js +475 -0
  52. package/dist/core/controllerServer.js +416 -27
  53. package/dist/core/controllerTelemetry.js +167 -0
  54. package/dist/doctor/doctor.js +113 -16
  55. package/dist/domain/validation.js +9 -0
  56. package/dist/execution/executionGroup.js +40 -3
  57. package/dist/executor/agentExecutor.js +6 -3
  58. package/dist/executor/effectiveLaunch.js +52 -0
  59. package/dist/executor/executorRegistry.js +50 -0
  60. package/dist/executor/fileRoleLaunchPlanner.js +61 -6
  61. package/dist/grant/capabilityGrant.js +282 -0
  62. package/dist/integration/changeSet.js +16 -3
  63. package/dist/integration/changeSetManifest.js +46 -0
  64. package/dist/integration/gitIntegrationService.js +528 -147
  65. package/dist/integration/integrationAttempt.js +54 -5
  66. package/dist/integration/integrationQueueEntry.js +221 -0
  67. package/dist/integration/integrationQueueService.js +955 -0
  68. package/dist/integration/manifestTags.js +99 -0
  69. package/dist/integration/overlapDiagnostics.js +211 -0
  70. package/dist/job/durableJob.js +449 -0
  71. package/dist/job/jobRunner.js +350 -0
  72. package/dist/lifecycle/exactRunTerminalization.js +24 -2
  73. package/dist/lifecycle/providerErrorClass.js +126 -0
  74. package/dist/message/message.js +16 -3
  75. package/dist/observability/executionAudit.js +545 -0
  76. package/dist/observability/faultClassification.js +160 -0
  77. package/dist/observability/runtimeIdentity.js +367 -0
  78. package/dist/release/fakeReleasePorts.js +55 -0
  79. package/dist/release/releaseHandover.js +475 -0
  80. package/dist/release/releaseIdempotencyStore.js +165 -0
  81. package/dist/release/releaseWorkflow.js +459 -0
  82. package/dist/release/releaseWorkflowEngine.js +688 -0
  83. package/dist/release/releaseWorkflowPorts.js +1720 -0
  84. package/dist/release/runtimeRelease.js +495 -0
  85. package/dist/release/workflowFileLock.js +218 -0
  86. package/dist/repository/gitWorkspace.js +177 -1
  87. package/dist/repository/projectMaintenanceLock.js +315 -0
  88. package/dist/repository/taskWorkspaceCoordinator.js +87 -17
  89. package/dist/repository/taskWorkspacePreparer.js +1091 -517
  90. package/dist/resources/autoResourceGc.js +116 -0
  91. package/dist/resources/liveReferences.js +574 -0
  92. package/dist/resources/resourceDiscovery.js +477 -0
  93. package/dist/resources/resourceGc.js +645 -0
  94. package/dist/resources/resourceRegistrar.js +256 -0
  95. package/dist/resources/resourceRegistry.js +150 -0
  96. package/dist/resources/resourceRegistryStore.js +41 -0
  97. package/dist/resources/resourceTypes.js +42 -0
  98. package/dist/resources/sqliteResourceRegistry.js +111 -0
  99. package/dist/review/reviewConfig.js +10 -0
  100. package/dist/review/reviewFinding.js +240 -0
  101. package/dist/review/reviewFindingLedger.js +545 -0
  102. package/dist/review/reviewOutcomeClassifier.js +61 -0
  103. package/dist/review/reviewRound.js +56 -4
  104. package/dist/run/agentRun.js +80 -4
  105. package/dist/run/providerRetry.js +84 -0
  106. package/dist/run/providerRetryConfig.js +63 -0
  107. package/dist/run/yieldReceipt.js +65 -0
  108. package/dist/runtime/exactControlPlane.js +79 -2
  109. package/dist/runtime/index.js +4 -0
  110. package/dist/runtime/sessionOwnerIdentity.js +269 -0
  111. package/dist/runtime/sessionOwnerRegistry.js +132 -0
  112. package/dist/runtime/sessionReconciliation.js +93 -0
  113. package/dist/runtime/sessionTerminationGuard.js +211 -0
  114. package/dist/runtime/taskRuntimeIsolation.js +13 -0
  115. package/dist/runtime/tmuxAdapters.js +34 -1
  116. package/dist/scheduler/actionability.js +155 -0
  117. package/dist/scheduler/activeRoleRunDelivery.js +14 -5
  118. package/dist/scheduler/activeTaskProgress.js +60 -0
  119. package/dist/scheduler/leaderWakeupProcessor.js +22 -11
  120. package/dist/scheduler/roleRunStall.js +135 -29
  121. package/dist/scheduler/taskExecutionProjection.js +11 -0
  122. package/dist/setup/setupCommand.js +27 -4
  123. package/dist/storage/compatibleTaskStore.js +112 -5
  124. package/dist/storage/migration/productionRegistry.js +769 -1
  125. package/dist/storage/persistenceWorker.js +194 -0
  126. package/dist/storage/sqliteSchema.js +705 -0
  127. package/dist/storage/sqliteStore.js +1695 -0
  128. package/dist/storage/storageVersions.js +9 -2
  129. package/dist/storage/storeRpc.js +298 -0
  130. package/dist/storage/taskStore.js +982 -21
  131. package/dist/storage/upgrade/homeClassification.js +157 -12
  132. package/dist/storage/upgrade/migrationReceipt.js +67 -0
  133. package/dist/storage/upgrade/pseudoLayoutRepair.js +241 -0
  134. package/dist/storage/upgrade/recordVersions.js +10 -1
  135. package/dist/storage/upgrade/sqliteMigrationTarget.js +351 -0
  136. package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +290 -0
  137. package/dist/storage/upgrade/sqliteStateMigration.js +713 -0
  138. package/dist/storage/upgrade/upgradeOrchestrator.js +510 -18
  139. package/dist/task/deliveryGuard.js +226 -0
  140. package/dist/task/nextAction.js +343 -0
  141. package/dist/task/repairWave.js +137 -0
  142. package/dist/task/taskRecordReference.js +6 -1
  143. package/dist/telemetry/sqliteTelemetryStore.js +387 -0
  144. package/dist/telemetry/telemetryCompaction.js +251 -0
  145. package/dist/telemetry/telemetryConfig.js +64 -0
  146. package/dist/telemetry/telemetryRouter.js +32 -0
  147. package/dist/telemetry/telemetryStore.js +19 -0
  148. package/dist/telemetry/telemetryWiring.js +33 -0
  149. package/dist/tmux/tmuxManager.js +20 -1
  150. package/dist/tmux/tmuxSocketEndpoint.js +20 -0
  151. package/dist/verification/gateArtifact.js +216 -0
  152. package/dist/verification/gateArtifactStore.js +87 -0
  153. package/dist/verification/verificationGateService.js +414 -0
  154. package/dist/verification/verificationPlan.js +308 -0
  155. package/dist/workspace/gitChangeSetCapture.js +12 -2
  156. package/dist/workspace/workItemChangeSetManager.js +60 -3
  157. package/package.json +2 -1
@@ -5,7 +5,14 @@
5
5
  * and `taskStore.ts` can all import them without creating a circular dependency.
6
6
  * `storageSchema.ts` re-exports them for backward compatibility.
7
7
  */
8
- /** Version of the on-disk layout (`schema.json`, root `state.json`, and locks). */
9
- export const CURRENT_STORAGE_LAYOUT_VERSION = 6;
8
+ /**
9
+ * Version of the on-disk layout (`schema.json`, root `state.json`, and locks).
10
+ *
11
+ * Layout 7 is the SQLite WAL control-plane layout (task-21 §8): the authoritative
12
+ * store moves from the aggregate `state.json` document to `yui.db`. A layout-6
13
+ * Home is migrated offline by the staged state.json→SQLite migration; layout 7
14
+ * is the current layout this release reads and writes.
15
+ */
16
+ export const CURRENT_STORAGE_LAYOUT_VERSION = 7;
10
17
  /** Version of the authoritative aggregate stored in `state.json`. */
11
18
  export const CURRENT_AGGREGATE_SCHEMA_VERSION = 18;
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Bounded RPC seam for the persistence Worker Thread (task-21, work-item-5).
3
+ *
4
+ * The main thread talks to the persistence worker (storage/persistenceWorker)
5
+ * over a `MessageChannel` port. The backpressure, cancellation, and
6
+ * fault-boundary machinery lives in the shared `core/boundedRpc` module; this
7
+ * module adds the storage dialect:
8
+ *
9
+ * - {@link AsyncTaskStore} ........ the async counterpart to `TaskStore`
10
+ * (design §6): every method returns a promise; the worker owns the
11
+ * `SqliteTaskStore` connection, the main thread never touches the db.
12
+ * - {@link AsyncTaskStoreClient} .. the client: serializes requests, applies
13
+ * the storage idempotency/dialect rules on top of the shared bounded RPC
14
+ * (outbox §5.4, `AbortSignal` cancellation §3.1, restart + replay §3.1).
15
+ * - {@link StoreCommand} .......... one variant per `TaskStore` op, so
16
+ * `transactionAsync` ships an ordered batch that the worker runs inside one
17
+ * `BEGIN IMMEDIATE … COMMIT` (§3.2).
18
+ *
19
+ * The file `TaskStore` remains the default for CLI tools and tests; the worker
20
+ * backend is opt-in via `YUI_STORE_BACKEND=sqlite` + `YUI_STORE_WORKER=1`
21
+ * ({@link resolveStoreWorkerEnabled}). Rollback to the file store is a config
22
+ * flip (§6).
23
+ */
24
+ import { BoundedRpcClient, nextRequestId } from "../core/boundedRpc.js";
25
+ import { StorageCancelledError, StorageConflictError, StorageRecordError } from "./taskStore.js";
26
+ import { resolveTaskStoreBackendForHome } from "./sqliteStore.js";
27
+ // -- Read-only classification ------------------------------------------------
28
+ /**
29
+ * TaskStore methods that do not mutate. Reads use the worker's read pool
30
+ * (separate WAL connections that never take the write lock, §3.2). Everything
31
+ * else is routed to the writer connection.
32
+ */
33
+ const READ_ONLY_STORE_METHODS = new Set([
34
+ "rootDirectory",
35
+ "getConfig",
36
+ "getHomeIdentity",
37
+ "getReviewConfig",
38
+ "getRevision",
39
+ "listConfiguredAgents",
40
+ "getConfiguredAgent",
41
+ "listProjects",
42
+ "getProject",
43
+ "listAgentProfiles",
44
+ "getAgentProfile",
45
+ "listGlobalRoles",
46
+ "getGlobalRole",
47
+ "getGlobalRoleSessionSet",
48
+ "listGlobalRoleSessionSets",
49
+ "listTasks",
50
+ "getTask",
51
+ "readNextActionFacts",
52
+ "listActiveTaskIds",
53
+ "getTaskBrief",
54
+ "listChangeSets",
55
+ "getChangeSet",
56
+ "listIntegrationAttempts",
57
+ "getIntegrationAttempt",
58
+ "listRoles",
59
+ "getRole",
60
+ "listManagedWorkspaces",
61
+ "listManagedWorkspace",
62
+ "getManagedWorkspace",
63
+ "getTaskWorkspace",
64
+ "getWorkItemWorkspace",
65
+ "getReviewRoundWorkspace",
66
+ "getIntegrationWorkspace",
67
+ "getRoleSessionSet",
68
+ "getTaskRoleSessionSet",
69
+ "listRoleSessionSets",
70
+ "getRoleSession",
71
+ "getWorkItem",
72
+ "listWorkItems",
73
+ "getAgentRun",
74
+ "listAgentRuns",
75
+ "listPendingProviderRetries",
76
+ "peekNextAgentRunId",
77
+ "getReviewRound",
78
+ "listReviewRuns",
79
+ "getActiveAgentRun",
80
+ "getActiveExecutionLaneRun",
81
+ "listMessages",
82
+ "getInputRequest",
83
+ "listInputRequests",
84
+ "listAllInputRequests",
85
+ "listDecisions",
86
+ "getDecision",
87
+ "listMilestones",
88
+ "getMilestone",
89
+ "listEvents",
90
+ "getWorkMailbox",
91
+ "listWorkMailboxes",
92
+ "getPendingWakeup",
93
+ "listPendingWakeups",
94
+ "getLeaderFailure",
95
+ "getOperatorNotification",
96
+ "listTelemetry",
97
+ "countTelemetry",
98
+ "hasOutboxEntry",
99
+ "listPendingOutbox"
100
+ ]);
101
+ function isReadOnlyMethod(method) {
102
+ return READ_ONLY_STORE_METHODS.has(method);
103
+ }
104
+ // -- Error deserialization (storage dialect) ---------------------------------
105
+ function deserializeError(serialized) {
106
+ const { name, message } = serialized;
107
+ if (name === "StorageConflictError")
108
+ return new StorageConflictError(message);
109
+ if (name === "StorageRecordError")
110
+ return new StorageRecordError(message);
111
+ if (name === "StorageCancelledError" || name === "AbortError") {
112
+ return new StorageCancelledError(message);
113
+ }
114
+ const error = new Error(message);
115
+ error.name = name;
116
+ return error;
117
+ }
118
+ // -- Storage protocol adapter -------------------------------------------------
119
+ function storageProtocol(home, options) {
120
+ return {
121
+ initRequest: () => ({
122
+ kind: "init",
123
+ home,
124
+ ...(options.readPoolSize === undefined ? {} : { readPoolSize: options.readPoolSize }),
125
+ ...(options.observerModule === undefined
126
+ ? {}
127
+ : { observerModule: String(options.observerModule) })
128
+ }),
129
+ cancelRequest: (requestId) => ({ kind: "cancel", requestId }),
130
+ shutdownRequest: () => ({ kind: "shutdown" }),
131
+ isReady: (response) => response.kind === "ready",
132
+ responseRequestId: (response) => {
133
+ if (response.kind === "ready") {
134
+ throw new Error("ready response has no requestId.");
135
+ }
136
+ return response.requestId;
137
+ },
138
+ settle: (response, settlement) => {
139
+ if (response.kind === "result") {
140
+ settlement.resolve(response.result);
141
+ return;
142
+ }
143
+ if (response.kind === "already-applied") {
144
+ // The effect committed before a crash; the retry is deduped (§5.4). The
145
+ // original result is not retained; callers needing it re-read. Observer
146
+ // callers treat `undefined` as "applied".
147
+ settlement.resolve(undefined);
148
+ return;
149
+ }
150
+ if (response.kind === "error") {
151
+ settlement.reject(deserializeError(response.error));
152
+ }
153
+ },
154
+ abortError: (beforeSend) => new StorageCancelledError(beforeSend ? "Request aborted before it was sent." : "Request aborted.")
155
+ };
156
+ }
157
+ // -- Client ------------------------------------------------------------------
158
+ /**
159
+ * The main-thread client for the persistence worker. Implements
160
+ * {@link AsyncTaskStore} (via a Proxy that forwards `TaskStore` methods as `call`
161
+ * RPCs) plus {@link transactionAsync}, {@link invokeObserver}, and {@link close}.
162
+ */
163
+ export class AsyncTaskStoreClient {
164
+ #home;
165
+ #options;
166
+ #rpc;
167
+ constructor(home, options = {}) {
168
+ this.#home = home;
169
+ this.#options = options;
170
+ this.#rpc = new BoundedRpcClient(storageProtocol(home, options), {
171
+ maxInFlight: options.maxInFlight,
172
+ maxQueue: options.maxQueue,
173
+ workerScript: options.workerScript ?? new URL("./persistenceWorker.js", import.meta.url)
174
+ });
175
+ }
176
+ /** Invoke a TaskStore method over the RPC (used by the Proxy). */
177
+ callStore(method, args, options) {
178
+ const requestId = options?.requestId ?? nextRequestId();
179
+ return this.#rpc.send(requestId, {
180
+ kind: "call",
181
+ requestId,
182
+ method,
183
+ args,
184
+ readOnly: isReadOnlyMethod(method)
185
+ }, { signal: options?.signal });
186
+ }
187
+ /** Run a command batch atomically in the worker (§3.2). */
188
+ transactionAsync(commands, options) {
189
+ const requestId = options?.requestId ?? nextRequestId();
190
+ const wireCommands = commands.map((command) => ({
191
+ op: command.op,
192
+ args: command.args
193
+ }));
194
+ return this.#rpc.send(requestId, {
195
+ kind: "transaction",
196
+ requestId,
197
+ commands: wireCommands,
198
+ ...(options?.expectedRevision === undefined ? {} : { expectedRevision: options.expectedRevision })
199
+ }, { signal: options?.signal });
200
+ }
201
+ /**
202
+ * Invoke a controller observer method hosted by the worker (the
203
+ * `FileSchedulerStoreAdapter` observer surface). The adapter's folds run in
204
+ * the worker, off the main event loop.
205
+ */
206
+ invokeObserver(method, args, options) {
207
+ const requestId = options?.requestId ?? nextRequestId();
208
+ return this.#rpc.send(requestId, { kind: "observer", requestId, method, args }, { signal: options?.signal });
209
+ }
210
+ /** Close the worker and release its connections. */
211
+ close() {
212
+ return this.#rpc.close();
213
+ }
214
+ /** Currently in-flight requests (metrics/tests). */
215
+ get inFlight() {
216
+ return this.#rpc.inFlight;
217
+ }
218
+ /** Currently queued requests waiting for a slot (metrics/tests). */
219
+ get queueDepth() {
220
+ return this.#rpc.queueDepth;
221
+ }
222
+ /**
223
+ * Test-only fault injection: abruptly terminate the worker (simulating a
224
+ * crash) so the exit handler restarts it and replays unacknowledged requests
225
+ * (§3.1 fault boundary). The pending requests stay pending; they resolve
226
+ * after the restart + replay.
227
+ */
228
+ crashForTest() {
229
+ return this.#rpc.crashForTest();
230
+ }
231
+ }
232
+ /**
233
+ * Open an {@link AsyncTaskStore} backed by the persistence worker. The returned
234
+ * object is a Proxy that forwards `TaskStore` methods as RPCs; `transactionAsync`
235
+ * and `close` are handled directly.
236
+ */
237
+ export function openAsyncTaskStoreClient(home, options = {}) {
238
+ const client = new AsyncTaskStoreClient(home, options);
239
+ const proxy = new Proxy(client, {
240
+ get(target, property) {
241
+ if (property === "then")
242
+ return undefined; // not promise-like
243
+ if (property in target) {
244
+ // Access on the target (not the proxy) so getters that touch private
245
+ // fields (#slots, etc.) resolve against the class instance.
246
+ const value = Reflect.get(target, property);
247
+ if (typeof value === "function")
248
+ return value.bind(target);
249
+ return value;
250
+ }
251
+ if (typeof property === "string") {
252
+ return (...args) => {
253
+ const options = args.length > 0 && isRpcCallOptions(args[args.length - 1])
254
+ ? args.pop()
255
+ : undefined;
256
+ return target.callStore(property, args, options);
257
+ };
258
+ }
259
+ return undefined;
260
+ }
261
+ });
262
+ return proxy;
263
+ }
264
+ function isRpcCallOptions(value) {
265
+ if (typeof value !== "object" || value === null)
266
+ return false;
267
+ const record = value;
268
+ return "requestId" in record || "signal" in record;
269
+ }
270
+ /**
271
+ * Resolve whether the persistence worker backend is enabled (design §6).
272
+ * The worker requires the SQLite backend (`YUI_STORE_BACKEND=sqlite`) and is
273
+ * opt-in via `YUI_STORE_WORKER=1`. The file store remains the default.
274
+ */
275
+ export function resolveStoreWorkerEnabled(env = process.env) {
276
+ if (env.YUI_STORE_BACKEND?.toLowerCase() !== "sqlite")
277
+ return false;
278
+ const flag = env.YUI_STORE_WORKER;
279
+ return flag === "1" || flag?.toLowerCase() === "true";
280
+ }
281
+ /**
282
+ * Resolve whether the persistence worker is enabled, from the Home's verified
283
+ * manifest (Issue 01). A Home-decided SQLite backend (layout 7, no explicit
284
+ * `YUI_STORE_BACKEND`) runs the worker by default — that is the product
285
+ * commitment layout 7 makes. An env-decided SQLite backend keeps the
286
+ * historical opt-in (`YUI_STORE_WORKER=1`). `YUI_STORE_WORKER=0/false`
287
+ * disables the worker in both cases (in-process SQLite still applies).
288
+ */
289
+ export function resolveStoreWorkerEnabledForHome(home, env = process.env) {
290
+ if (resolveTaskStoreBackendForHome(home, env) !== "sqlite")
291
+ return false;
292
+ const flag = env.YUI_STORE_WORKER?.toLowerCase();
293
+ if (flag === "1" || flag === "true")
294
+ return true;
295
+ if (flag === "0" || flag === "false")
296
+ return false;
297
+ return env.YUI_STORE_BACKEND?.toLowerCase() !== "sqlite";
298
+ }