@zq-silk/yui 0.14.0 → 0.14.2

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 (179) hide show
  1. package/ARCHITECTURE.md +64 -35
  2. package/README.md +258 -125
  3. package/dist/agent/argumentPolicy.js +2 -1
  4. package/dist/agent/managedRuntimeEnvironment.js +5 -8
  5. package/dist/cli/commandCatalog.js +74 -109
  6. package/dist/cli/helpRenderer.js +1 -2
  7. package/dist/cli/interactionCandidates.js +10 -0
  8. package/dist/cli/interactionPolicy.js +76 -37
  9. package/dist/cli/roleWizard.js +5 -6
  10. package/dist/cli/updateOrchestrator.js +10 -8
  11. package/dist/cli/updatePorts.js +17 -13
  12. package/dist/cli/upgradeCommand.js +2 -5
  13. package/dist/cli.js +268 -231
  14. package/dist/commands/agentCommands.js +13 -0
  15. package/dist/commands/configCommands.js +7 -19
  16. package/dist/commands/configOverview.js +3 -2
  17. package/dist/commands/durableJobCommands.js +1 -1
  18. package/dist/commands/executionAuditCommands.js +4 -9
  19. package/dist/commands/globalRoleCommands.js +17 -0
  20. package/dist/commands/profileCommands.js +200 -30
  21. package/dist/commands/sessionCommands.js +1 -1
  22. package/dist/commands/taskActor.js +29 -127
  23. package/dist/commands/taskChangeSetCommands.js +1 -3
  24. package/dist/commands/taskCommands.js +1771 -2107
  25. package/dist/commands/taskCompletionGate.js +27 -103
  26. package/dist/commands/taskContextCommand.js +47 -80
  27. package/dist/commands/taskExecutionCommands.js +9 -27
  28. package/dist/commands/taskInputCommands.js +10 -10
  29. package/dist/commands/taskIntegrationCommands.js +69 -61
  30. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  31. package/dist/commands/taskNextActionCommand.js +8 -29
  32. package/dist/commands/taskOverviewCommand.js +25 -3
  33. package/dist/commands/taskPublicationCommands.js +151 -85
  34. package/dist/commands/taskPublicationVerifyCommand.js +181 -0
  35. package/dist/commands/taskRemoteDeliveryCommand.js +134 -0
  36. package/dist/commands/taskRoleRuntimeStatus.js +5 -6
  37. package/dist/commands/taskUpstreamCommands.js +79 -95
  38. package/dist/config/configCatalog.js +1 -1
  39. package/dist/context/contextSnapshot.js +17 -2
  40. package/dist/context/sessionBootstrapManifest.js +18 -1
  41. package/dist/context/sourceTurnContext.js +30 -0
  42. package/dist/context/turnContextPack.js +107 -48
  43. package/dist/context/turnInputContract.js +11 -4
  44. package/dist/context/wakeNotification.js +84 -22
  45. package/dist/controller/agentRuntimeObserver.js +9 -12
  46. package/dist/controller/clientRuntime.js +13 -13
  47. package/dist/controller/controller.js +11 -11
  48. package/dist/controller/fileSchedulerStoreAdapter.js +262 -219
  49. package/dist/controller/jobControl.js +11 -10
  50. package/dist/controller/resourceInventory.js +6 -6
  51. package/dist/controller/resourceInventoryLinux.js +2 -2
  52. package/dist/controller/runtime.js +18 -61
  53. package/dist/controller/runtimeEventInbox.js +57 -34
  54. package/dist/controller/runtimeEventProcessor.js +36 -96
  55. package/dist/controller/runtimeHookTurnFence.js +33 -57
  56. package/dist/controller/runtimeLaunchCoordinator.js +44 -40
  57. package/dist/controller/runtimeObservationHook.js +18 -12
  58. package/dist/controller/sessionNotify.js +43 -28
  59. package/dist/controller/sessionOwnerReconciliation.js +21 -21
  60. package/dist/controller/structuredProviderObservation.js +13 -16
  61. package/dist/coordination/workMailboxQueue.js +132 -0
  62. package/dist/core/controllerServer.js +1 -0
  63. package/dist/domain/agentResultTransport.js +60 -0
  64. package/dist/execution/executionHealth.js +111 -118
  65. package/dist/execution/reviewMainTurn.js +161 -0
  66. package/dist/execution/workItemExecution.js +454 -0
  67. package/dist/execution/workItemExecutionProjection.js +309 -0
  68. package/dist/execution/workItemMainTurn.js +164 -0
  69. package/dist/executor/agentExecutor.js +19 -19
  70. package/dist/executor/executorRegistry.js +7 -28
  71. package/dist/executor/fileRoleLaunchPlanner.js +51 -83
  72. package/dist/external/githubPublicationVerifier.js +114 -0
  73. package/dist/external/gitlabPublicationVerifier.js +158 -0
  74. package/dist/external/pinnedCommandRunner.js +73 -0
  75. package/dist/integration/changeSetManifest.js +0 -3
  76. package/dist/integration/deliveryObligation.js +43 -6
  77. package/dist/integration/gitIntegrationService.js +284 -101
  78. package/dist/integration/integrationAttempt.js +64 -14
  79. package/dist/integration/integrationQueueEntry.js +5 -35
  80. package/dist/integration/integrationQueueService.js +65 -194
  81. package/dist/lifecycle/canonicalLifecycleEvent.js +16 -15
  82. package/dist/lifecycle/exactTurnTerminalization.js +100 -97
  83. package/dist/message/message.js +16 -0
  84. package/dist/observability/executionAudit.js +4 -25
  85. package/dist/observability/faultClassification.js +58 -70
  86. package/dist/observability/orchestrationMetrics.js +8 -50
  87. package/dist/profile/agentProfile.js +60 -15
  88. package/dist/profile/agentProfileRuntime.js +100 -0
  89. package/dist/release/releaseWorkflowPorts.js +5 -68
  90. package/dist/repository/executionLaneGitSnapshot.js +80 -0
  91. package/dist/repository/gitWorkspace.js +9 -67
  92. package/dist/repository/taskBaseFreshness.js +3 -1
  93. package/dist/repository/taskWorkspaceCoordinator.js +32 -4
  94. package/dist/repository/taskWorkspacePreparer.js +252 -411
  95. package/dist/resources/liveReferences.js +6 -55
  96. package/dist/resources/resourceDiscovery.js +1 -30
  97. package/dist/resources/resourceRegistrar.js +0 -23
  98. package/dist/review/deltaRecheck.js +8 -65
  99. package/dist/review/reviewAcceptance.js +22 -19
  100. package/dist/review/reviewConfig.js +0 -10
  101. package/dist/review/reviewDecision.js +2 -2
  102. package/dist/review/reviewRound.js +147 -273
  103. package/dist/review/reviewerAvailability.js +13 -23
  104. package/dist/role/role.js +3 -0
  105. package/dist/runtime/agentDriverObservation.js +1 -1
  106. package/dist/runtime/agentHost.js +51 -51
  107. package/dist/runtime/builtinAgentDrivers.js +9 -2
  108. package/dist/runtime/codexAppServerRuntime.js +23 -5
  109. package/dist/runtime/exactControlPlane.js +2 -267
  110. package/dist/runtime/firstProgressAdvisory.js +1 -1
  111. package/dist/runtime/index.js +1 -1
  112. package/dist/runtime/launchBroker.js +11 -11
  113. package/dist/runtime/lifecycleReservation.js +2 -2
  114. package/dist/runtime/managedCaller.js +111 -0
  115. package/dist/runtime/ports.js +16 -3
  116. package/dist/runtime/preallocatedNativeSession.js +2 -2
  117. package/dist/runtime/processExitObservation.js +3 -2
  118. package/dist/runtime/providerContinuationReconciliationService.js +1 -1
  119. package/dist/runtime/runtimeBinding.js +1 -1
  120. package/dist/runtime/runtimeObservation.js +33 -16
  121. package/dist/runtime/runtimeSessionCandidate.js +2 -2
  122. package/dist/runtime/runtimeStopReceipt.js +11 -11
  123. package/dist/runtime/sessionLaunchRequest.js +2 -2
  124. package/dist/runtime/sessionOwnerIdentity.js +9 -9
  125. package/dist/runtime/sessionOwnerRegistry.js +13 -13
  126. package/dist/runtime/sessionReconciliation.js +4 -4
  127. package/dist/runtime/sessionTerminationGuard.js +9 -9
  128. package/dist/runtime/sessionTokenMetrics.js +5 -7
  129. package/dist/runtime/structuredProviderHost.js +5 -5
  130. package/dist/runtime/taskRuntimeIsolation.js +24 -24
  131. package/dist/runtime/tmuxAdapters.js +32 -30
  132. package/dist/scheduler/activeRoleTurnDelivery.js +37 -15
  133. package/dist/scheduler/leaderWakeupProcessor.js +78 -55
  134. package/dist/scheduler/roleTurnLiveness.js +6 -6
  135. package/dist/scheduler/roleTurnStall.js +8 -9
  136. package/dist/scheduler/taskExecutionProjection.js +19 -41
  137. package/dist/scheduler/taskObservabilityProjection.js +75 -122
  138. package/dist/storage/sqliteSchema.js +1 -21
  139. package/dist/storage/sqliteStore.js +62 -47
  140. package/dist/storage/storageSchema.js +1 -8
  141. package/dist/storage/storageVersions.js +7 -4
  142. package/dist/storage/taskStore.js +8 -8
  143. package/dist/storage/upgrade/upgradeOrchestrator.js +112 -83
  144. package/dist/task/completionReadiness.js +17 -98
  145. package/dist/task/deliveryGuard.js +9 -11
  146. package/dist/task/draftPlan.js +142 -0
  147. package/dist/task/nextAction.js +179 -477
  148. package/dist/task/publicationVerification.js +1 -0
  149. package/dist/task/remoteDelivery.js +233 -0
  150. package/dist/task/task.js +108 -4
  151. package/dist/task/taskRecordReference.js +0 -1
  152. package/dist/turn/turn.js +109 -16
  153. package/dist/verification/verificationGateService.js +0 -26
  154. package/dist/web/assets/client/components.js +99 -121
  155. package/dist/web/assets/client/i18n.js +136 -58
  156. package/dist/web/assets/client/view.js +44 -0
  157. package/dist/web/assets/styles/cards.js +3 -15
  158. package/dist/web/assets/styles/widgets.js +4 -0
  159. package/dist/web/webSnapshot.js +29 -14
  160. package/dist/workItem/dependencyGate.js +34 -0
  161. package/dist/workItem/workItem.js +99 -266
  162. package/dist/workspace/workItemChangeSetManager.js +15 -59
  163. package/docs/task-local-identity.md +1 -1
  164. package/i18n/README.zh-CN.md +165 -59
  165. package/package.json +1 -1
  166. package/skills/yui-leader/SKILL.md +272 -782
  167. package/skills/yui-operator/SKILL.md +190 -365
  168. package/skills/yui-reviewer/SKILL.md +40 -33
  169. package/skills/yui-runtime/SKILL.md +27 -6
  170. package/skills/yui-worker/SKILL.md +19 -6
  171. package/dist/execution/candidateConvergence.js +0 -623
  172. package/dist/execution/executionGroup.js +0 -854
  173. package/dist/execution/resourceBroker.js +0 -426
  174. package/dist/executor/launchPlan.js +0 -16
  175. package/dist/review/reviewFinding.js +0 -240
  176. package/dist/review/reviewFindingLedger.js +0 -550
  177. package/dist/review/reviewOutcomeClassifier.js +0 -255
  178. package/dist/scheduler/resourceQueueProjection.js +0 -71
  179. package/dist/task/repairWave.js +0 -150
@@ -0,0 +1,80 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ /**
4
+ * Freeze the exact committed heads of a durable managed Lane workspace at the
5
+ * synchronous runtime-terminalization boundary. Runtime event folds are
6
+ * synchronous inside the SQLite aggregate transaction, so this small Git read
7
+ * cannot use the asynchronous workspace-preparation port.
8
+ */
9
+ export function snapshotExecutionLaneWorkspaceSync(store, workspace) {
10
+ if (workspace.owner.type !== "execution-lane") {
11
+ throw new Error("Only an Execution Lane workspace can freeze a producer result.");
12
+ }
13
+ const stored = store.getManagedWorkspace(workspace.owner);
14
+ if (stored === null || !isDeepStrictEqual(stored, workspace)) {
15
+ throw new Error("Execution Lane managed workspace is not the durable owner.");
16
+ }
17
+ const writable = workspace.entries.filter(({ access }) => access === "write");
18
+ if (writable.length === 0) {
19
+ return {
20
+ status: "failed",
21
+ cause: "no-writable-project",
22
+ diagnostic: "Core could not freeze an Execution Lane with no writable Project."
23
+ };
24
+ }
25
+ const projects = [];
26
+ for (const entry of writable) {
27
+ const status = git(entry.path, ["status", "--porcelain"]);
28
+ if (status === undefined) {
29
+ return {
30
+ status: "failed",
31
+ cause: "workspace-unavailable",
32
+ diagnostic: `Core could not inspect writable Project ${entry.projectId} at ${entry.path}.`
33
+ };
34
+ }
35
+ if (status.length > 0) {
36
+ return {
37
+ status: "failed",
38
+ cause: "workspace-dirty",
39
+ diagnostic: `Writable Project ${entry.projectId} is dirty; Core did not accept the Lane result.`
40
+ };
41
+ }
42
+ const branch = git(entry.path, ["symbolic-ref", "--quiet", "--short", "HEAD"]);
43
+ const headCommit = git(entry.path, ["rev-parse", "--verify", "HEAD^{commit}"]);
44
+ if (branch === undefined || headCommit === undefined) {
45
+ return {
46
+ status: "failed",
47
+ cause: "workspace-unavailable",
48
+ diagnostic: `Core could not resolve the branch and commit for writable Project ${entry.projectId}.`
49
+ };
50
+ }
51
+ if (branch !== entry.branch) {
52
+ return {
53
+ status: "failed",
54
+ cause: "branch-mismatch",
55
+ diagnostic: `Writable Project ${entry.projectId} is on branch ${branch}; expected ${entry.branch}.`
56
+ };
57
+ }
58
+ projects.push({
59
+ projectId: entry.projectId,
60
+ headCommit: headCommit.toLowerCase(),
61
+ branch
62
+ });
63
+ }
64
+ return {
65
+ status: "captured",
66
+ snapshot: { schemaVersion: 1, projects }
67
+ };
68
+ }
69
+ function git(cwd, args) {
70
+ try {
71
+ return execFileSync("git", args, {
72
+ cwd,
73
+ encoding: "utf8",
74
+ stdio: ["ignore", "pipe", "pipe"]
75
+ }).trim();
76
+ }
77
+ catch {
78
+ return undefined;
79
+ }
80
+ }
@@ -70,10 +70,8 @@ export class NodeGitWorkspace {
70
70
  ]);
71
71
  }
72
72
  /**
73
- * Every path changed between two commits. The integration queue uses this
74
- * to fence a validated entry: a target advance whose real path delta
75
- * overlaps the entry's own paths (or whose impact cannot be proven)
76
- * invalidates the entry's reusable evidence.
73
+ * Every path changed between two commits. Freshness and delta-review
74
+ * projections use this as objective Git evidence.
77
75
  */
78
76
  async changedFilesBetween(input) {
79
77
  const output = await git([
@@ -135,69 +133,6 @@ export class NodeGitWorkspace {
135
133
  const commit = await resolveRemoteBranchCommit(remote, branch);
136
134
  return { branch, commit };
137
135
  }
138
- /**
139
- * Merge a remote Project baseline into a clean, managed worktree. The
140
- * fetch is performed from that worktree and the stable checkout is never
141
- * touched. Fast-forward updates are preferred; a diverged baseline gets a
142
- * deterministic merge commit so the caller can run its normal Integration
143
- * checks and CAS the target ref.
144
- */
145
- async mergeRemoteIntoWorktree(input) {
146
- const initial = await this.inspect(input.repositoryPath, "HEAD");
147
- if (!await this.isClean(initial.root)) {
148
- throw new Error("Managed Task/Integration worktree must be clean before remote merge.");
149
- }
150
- const fetched = await this.#fetchRemoteHeadIntoWorktree(input);
151
- const fetchedCommit = fetched.commit;
152
- const fetchedRef = fetched.fetchedRef;
153
- try {
154
- if (fetchedCommit === initial.baseCommit) {
155
- return { fromCommit: initial.baseCommit, toCommit: fetchedCommit, changed: false };
156
- }
157
- if (await gitSucceeds([
158
- "-C", initial.root,
159
- "merge-base", "--is-ancestor", fetchedCommit, initial.baseCommit
160
- ])) {
161
- // The Task already contains the current remote baseline.
162
- return { fromCommit: initial.baseCommit, toCommit: initial.baseCommit, changed: false };
163
- }
164
- if (await gitSucceeds([
165
- "-C", initial.root,
166
- "merge-base", "--is-ancestor", initial.baseCommit, fetchedCommit
167
- ])) {
168
- await git(["-C", initial.root, "merge", "--ff-only", "--no-edit", fetchedRef]);
169
- }
170
- else {
171
- try {
172
- await git([
173
- "-C", initial.root,
174
- "-c", "user.name=Yui",
175
- "-c", "user.email=yui@local",
176
- "merge", "--no-edit", "--no-ff", fetchedRef
177
- ]);
178
- }
179
- catch (error) {
180
- const affected = (await git([
181
- "-C", initial.root,
182
- "diff", "--name-only", "--diff-filter=U"
183
- ])).trim().split("\n").filter(Boolean);
184
- const suffix = affected.length === 0 ? "" : ` (${affected.join(", ")})`;
185
- throw new RemoteBaselineConflictError(affected, `Remote baseline merge conflicts in managed worktree${suffix}; resolve it in the Integration workspace.`, { cause: error });
186
- }
187
- }
188
- const mergedCommit = (await gitLine([
189
- "-C", initial.root,
190
- "rev-parse", "--verify", "--end-of-options", "HEAD^{commit}"
191
- ])).toLowerCase();
192
- if (!await this.isClean(initial.root)) {
193
- throw new Error("Remote baseline merge left the managed worktree dirty.");
194
- }
195
- return { fromCommit: initial.baseCommit, toCommit: mergedCommit, changed: true };
196
- }
197
- finally {
198
- await gitSucceeds(["-C", initial.root, "update-ref", "-d", fetchedRef]);
199
- }
200
- }
201
136
  /** Fetch a remote branch into a managed worktree without changing HEAD. */
202
137
  async fetchRemoteHeadIntoWorktree(input) {
203
138
  const fetched = await this.#fetchRemoteHeadIntoWorktree(input);
@@ -339,6 +274,13 @@ export class NodeGitWorkspace {
339
274
  remote,
340
275
  destination
341
276
  ]);
277
+ if (input.localBranch !== undefined) {
278
+ const localBranch = safeRef(input.localBranch);
279
+ if (!await gitSucceeds(["check-ref-format", "--branch", localBranch])) {
280
+ throw new Error(`Local clone branch is invalid: ${localBranch}.`);
281
+ }
282
+ await git(["-C", destination, "branch", "-M", "--", localBranch]);
283
+ }
342
284
  }
343
285
  catch (error) {
344
286
  await rm(destination, { recursive: true, force: true });
@@ -187,6 +187,8 @@ function requireProject(store, projectId) {
187
187
  async function resolveBaseCommit(git, project, binding, entry) {
188
188
  if (entry?.baseCommit !== undefined)
189
189
  return entry.baseCommit;
190
+ if (binding.baseCommit !== undefined)
191
+ return binding.baseCommit;
190
192
  if (COMMIT_PATTERN.test(binding.baseRef))
191
193
  return binding.baseRef.toLowerCase();
192
194
  return (await git.inspect(project.path, binding.baseRef)).baseCommit;
@@ -225,7 +227,7 @@ async function resolveTracked(git, project, workspacePath, refresh) {
225
227
  }
226
228
  }
227
229
  const tracking = await git.inspectRemoteTracking({
228
- repositoryPath: project.path,
230
+ repositoryPath: workspacePath,
229
231
  remoteUrl: project.remoteUrl,
230
232
  branch: project.developmentBranch
231
233
  });
@@ -171,6 +171,7 @@ export class TaskWorkspaceCoordinator {
171
171
  }
172
172
  releaseMaintenance = acquireProjectMaintenanceLocks(this.preparer.home, projectIds);
173
173
  const laneWorkspaces = managedWorkspaces.filter(({ owner }) => owner.type === "execution-lane");
174
+ const integrationWorkspaces = managedWorkspaces.filter(({ owner }) => owner.type === "integration-attempt");
174
175
  const workspaces = managedWorkspaces
175
176
  .filter(({ owner }) => owner.type === "work-item");
176
177
  const workItems = workspaces.map((workspace) => {
@@ -240,6 +241,28 @@ export class TaskWorkspaceCoordinator {
240
241
  };
241
242
  }
242
243
  }
244
+ for (const workspace of integrationWorkspaces) {
245
+ if (workspace.owner.type !== "integration-attempt")
246
+ continue;
247
+ const attempt = this.store.getIntegrationAttempt(task.id, workspace.owner.integrationAttemptId);
248
+ if (attempt === null
249
+ || attempt.status === "running"
250
+ || attempt.status === "blocked"
251
+ || attempt.status === "validating") {
252
+ throw new Error(`IntegrationAttempt must be terminal before archive cleanup: ${workspace.owner.integrationAttemptId}.`);
253
+ }
254
+ if (await this.preparer.inspectIntegrationWorkspace(task.id, attempt.id) === "dirty") {
255
+ return {
256
+ taskId,
257
+ status: "retained-dirty",
258
+ ...(task.cwd === undefined ? {} : { path: task.cwd }),
259
+ error: `Integration worktree is dirty: ${attempt.id}.`,
260
+ reason: "dirty-worktree",
261
+ resource: `integration-attempt:${task.id}/${attempt.id}`,
262
+ retryable: true
263
+ };
264
+ }
265
+ }
243
266
  const state = await this.preparer.inspectTaskMainWorkspace(taskId);
244
267
  if (state === "dirty") {
245
268
  return {
@@ -258,9 +281,7 @@ export class TaskWorkspaceCoordinator {
258
281
  throw new WorkspaceCleanupBlockedError("active-turn", `role:${task.id}/${activeRole.name}`, true, `Task Role still has an active Turn: ${task.id}/${activeRole.name}.`);
259
282
  }
260
283
  const roleNames = this.store.listRoles(taskId).map(({ name }) => name);
261
- if (roleNames.length > 0) {
262
- await this.runtime.stopTaskRoleSessions(taskId, roleNames);
263
- }
284
+ await this.#stopLiveRoles(taskId, roleNames);
264
285
  await this.runtime.assertTaskPhysicalResourcesReleased?.(task.id);
265
286
  this.#assertTaskArchiveSnapshot(snapshot);
266
287
  for (const workspace of laneWorkspaces) {
@@ -269,6 +290,12 @@ export class TaskWorkspaceCoordinator {
269
290
  await this.preparer.cleanupExecutionLaneWorkspace(task.id, workspace.owner.executionGroupId, workspace.owner.executionLaneId);
270
291
  }
271
292
  }
293
+ for (const workspace of integrationWorkspaces) {
294
+ this.#assertTaskArchiveLifecycle(task);
295
+ if (workspace.owner.type === "integration-attempt") {
296
+ await this.preparer.cleanupIntegrationWorkspace(task.id, workspace.owner.integrationAttemptId);
297
+ }
298
+ }
272
299
  for (const round of reviewRounds) {
273
300
  this.#assertTaskArchiveLifecycle(task);
274
301
  await this.preparer.cleanupReviewRoundWorkspace(task.id, round.id);
@@ -357,12 +384,13 @@ export class TaskWorkspaceCoordinator {
357
384
  #workItemRoleNames(item) {
358
385
  return [
359
386
  ...(item.assignee === undefined ? [] : [item.assignee]),
360
- ...(item.executionGroups.flatMap((group) => group.lanes.map(({ roleName }) => roleName)))
387
+ ...item.executionGroups.flatMap((group) => group.lanes.map(({ roleName }) => roleName))
361
388
  ];
362
389
  }
363
390
  #reviewRoundRoleNames(round) {
364
391
  return [
365
392
  round.reviewerRoleName,
393
+ ...(round.executionGroup?.lanes.map(({ roleName }) => roleName) ?? []),
366
394
  ...(round.executionGroup?.lanes.map(({ roleName }) => roleName) ?? [])
367
395
  ];
368
396
  }