@zq-silk/yui 0.6.0 → 0.6.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 (150) hide show
  1. package/README.md +5 -5
  2. package/dist/agent/managedRuntimeEnvironment.js +2 -1
  3. package/dist/cli/commandCatalog.js +251 -13
  4. package/dist/cli/updateOrchestrator.js +8 -0
  5. package/dist/cli/updatePorts.js +76 -22
  6. package/dist/cli.js +264 -20
  7. package/dist/commands/configCommands.js +83 -9
  8. package/dist/commands/controllerCommands.js +103 -0
  9. package/dist/commands/deliveryGuardPreflight.js +30 -0
  10. package/dist/commands/durableJobCommands.js +231 -0
  11. package/dist/commands/executionAuditCommands.js +193 -0
  12. package/dist/commands/grantCommands.js +374 -0
  13. package/dist/commands/projectCommands.js +119 -81
  14. package/dist/commands/releaseCommands.js +444 -0
  15. package/dist/commands/resourcesCommands.js +274 -0
  16. package/dist/commands/sessionCommands.js +104 -0
  17. package/dist/commands/taskActor.js +117 -0
  18. package/dist/commands/taskChangeSetCommands.js +60 -0
  19. package/dist/commands/taskCommands.js +618 -202
  20. package/dist/commands/taskCompletionGate.js +78 -1
  21. package/dist/commands/taskContextCommand.js +33 -6
  22. package/dist/commands/taskInputCommands.js +1 -1
  23. package/dist/commands/taskIntegrationCommands.js +136 -33
  24. package/dist/commands/taskIntegrationQueueCommands.js +228 -0
  25. package/dist/commands/taskNextActionCommand.js +100 -0
  26. package/dist/commands/taskOverlapCommands.js +120 -0
  27. package/dist/commands/taskOverviewCommand.js +36 -8
  28. package/dist/commands/telemetryCommands.js +330 -0
  29. package/dist/commands/workflowCommands.js +415 -0
  30. package/dist/config/yuiConfig.js +62 -0
  31. package/dist/controller/clientRuntime.js +42 -1
  32. package/dist/controller/controller.js +402 -56
  33. package/dist/controller/controllerMain.js +25 -2
  34. package/dist/controller/domainIdentity.js +16 -8
  35. package/dist/controller/fileSchedulerStoreAdapter.js +423 -31
  36. package/dist/controller/handoverCandidate.js +168 -0
  37. package/dist/controller/jobClient.js +102 -0
  38. package/dist/controller/jobControl.js +613 -0
  39. package/dist/controller/jobSupervisor.js +498 -0
  40. package/dist/controller/providerHookRunFence.js +34 -5
  41. package/dist/controller/resourceCleanupLinux.js +18 -9
  42. package/dist/controller/resourceInventoryLinux.js +90 -39
  43. package/dist/controller/runtime.js +165 -15
  44. package/dist/controller/runtimeEventInbox.js +234 -57
  45. package/dist/controller/runtimeEventProcessor.js +297 -58
  46. package/dist/controller/sessionOwnerReconciliation.js +321 -0
  47. package/dist/core/controllerServer.js +416 -27
  48. package/dist/core/controllerTelemetry.js +167 -0
  49. package/dist/doctor/doctor.js +113 -16
  50. package/dist/domain/validation.js +9 -0
  51. package/dist/execution/executionGroup.js +40 -3
  52. package/dist/executor/agentExecutor.js +6 -3
  53. package/dist/executor/effectiveLaunch.js +52 -0
  54. package/dist/executor/executorRegistry.js +50 -0
  55. package/dist/executor/fileRoleLaunchPlanner.js +61 -6
  56. package/dist/grant/capabilityGrant.js +282 -0
  57. package/dist/integration/changeSet.js +16 -3
  58. package/dist/integration/changeSetManifest.js +46 -0
  59. package/dist/integration/gitIntegrationService.js +528 -147
  60. package/dist/integration/integrationAttempt.js +54 -5
  61. package/dist/integration/integrationQueueEntry.js +221 -0
  62. package/dist/integration/integrationQueueService.js +955 -0
  63. package/dist/integration/manifestTags.js +99 -0
  64. package/dist/integration/overlapDiagnostics.js +211 -0
  65. package/dist/job/durableJob.js +449 -0
  66. package/dist/job/jobRunner.js +350 -0
  67. package/dist/lifecycle/exactRunTerminalization.js +24 -2
  68. package/dist/lifecycle/providerErrorClass.js +126 -0
  69. package/dist/message/message.js +16 -3
  70. package/dist/observability/executionAudit.js +545 -0
  71. package/dist/observability/faultClassification.js +160 -0
  72. package/dist/observability/runtimeIdentity.js +367 -0
  73. package/dist/release/fakeReleasePorts.js +55 -0
  74. package/dist/release/releaseHandover.js +475 -0
  75. package/dist/release/releaseIdempotencyStore.js +165 -0
  76. package/dist/release/releaseWorkflow.js +459 -0
  77. package/dist/release/releaseWorkflowEngine.js +688 -0
  78. package/dist/release/releaseWorkflowPorts.js +1720 -0
  79. package/dist/release/runtimeRelease.js +495 -0
  80. package/dist/release/workflowFileLock.js +218 -0
  81. package/dist/repository/gitWorkspace.js +177 -1
  82. package/dist/repository/projectMaintenanceLock.js +315 -0
  83. package/dist/repository/taskWorkspaceCoordinator.js +87 -17
  84. package/dist/repository/taskWorkspacePreparer.js +1091 -517
  85. package/dist/resources/autoResourceGc.js +116 -0
  86. package/dist/resources/liveReferences.js +574 -0
  87. package/dist/resources/resourceDiscovery.js +477 -0
  88. package/dist/resources/resourceGc.js +645 -0
  89. package/dist/resources/resourceRegistrar.js +256 -0
  90. package/dist/resources/resourceRegistry.js +150 -0
  91. package/dist/resources/resourceRegistryStore.js +41 -0
  92. package/dist/resources/resourceTypes.js +42 -0
  93. package/dist/resources/sqliteResourceRegistry.js +111 -0
  94. package/dist/review/reviewConfig.js +10 -0
  95. package/dist/review/reviewFinding.js +240 -0
  96. package/dist/review/reviewFindingLedger.js +545 -0
  97. package/dist/review/reviewOutcomeClassifier.js +61 -0
  98. package/dist/review/reviewRound.js +56 -4
  99. package/dist/run/agentRun.js +80 -4
  100. package/dist/run/providerRetry.js +84 -0
  101. package/dist/run/providerRetryConfig.js +63 -0
  102. package/dist/run/yieldReceipt.js +65 -0
  103. package/dist/runtime/exactControlPlane.js +79 -2
  104. package/dist/runtime/index.js +4 -0
  105. package/dist/runtime/sessionOwnerIdentity.js +269 -0
  106. package/dist/runtime/sessionOwnerRegistry.js +132 -0
  107. package/dist/runtime/sessionReconciliation.js +93 -0
  108. package/dist/runtime/sessionTerminationGuard.js +211 -0
  109. package/dist/runtime/taskRuntimeIsolation.js +13 -0
  110. package/dist/runtime/tmuxAdapters.js +34 -1
  111. package/dist/scheduler/actionability.js +155 -0
  112. package/dist/scheduler/activeRoleRunDelivery.js +14 -5
  113. package/dist/scheduler/activeTaskProgress.js +60 -0
  114. package/dist/scheduler/leaderWakeupProcessor.js +22 -11
  115. package/dist/scheduler/roleRunStall.js +135 -29
  116. package/dist/scheduler/taskExecutionProjection.js +11 -0
  117. package/dist/storage/compatibleTaskStore.js +112 -5
  118. package/dist/storage/migration/productionRegistry.js +736 -1
  119. package/dist/storage/sqliteSchema.js +264 -3
  120. package/dist/storage/sqliteStore.js +487 -13
  121. package/dist/storage/storeRpc.js +21 -0
  122. package/dist/storage/taskStore.js +974 -21
  123. package/dist/storage/upgrade/homeClassification.js +120 -2
  124. package/dist/storage/upgrade/migrationReceipt.js +67 -0
  125. package/dist/storage/upgrade/pseudoLayoutRepair.js +241 -0
  126. package/dist/storage/upgrade/recordVersions.js +10 -1
  127. package/dist/storage/upgrade/sqliteMigrationTarget.js +58 -6
  128. package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +290 -0
  129. package/dist/storage/upgrade/sqliteStateMigration.js +258 -2
  130. package/dist/storage/upgrade/upgradeOrchestrator.js +482 -16
  131. package/dist/task/deliveryGuard.js +226 -0
  132. package/dist/task/nextAction.js +738 -0
  133. package/dist/task/repairWave.js +137 -0
  134. package/dist/task/taskRecordReference.js +6 -1
  135. package/dist/telemetry/sqliteTelemetryStore.js +387 -0
  136. package/dist/telemetry/telemetryCompaction.js +251 -0
  137. package/dist/telemetry/telemetryConfig.js +64 -0
  138. package/dist/telemetry/telemetryRouter.js +32 -0
  139. package/dist/telemetry/telemetryStore.js +19 -0
  140. package/dist/telemetry/telemetryWiring.js +33 -0
  141. package/dist/tmux/tmuxManager.js +20 -1
  142. package/dist/tmux/tmuxSocketEndpoint.js +20 -0
  143. package/dist/verification/gateArtifact.js +216 -0
  144. package/dist/verification/gateArtifactStore.js +87 -0
  145. package/dist/verification/verificationGateService.js +414 -0
  146. package/dist/verification/verificationPlan.js +308 -0
  147. package/dist/workspace/gitChangeSetCapture.js +12 -2
  148. package/dist/workspace/workItemChangeSetManager.js +60 -3
  149. package/package.json +1 -1
  150. package/skills/yui-leader/SKILL.md +8 -0
@@ -0,0 +1,226 @@
1
+ const OPEN_WORK_ITEM_STATUSES = new Set(["pending", "running", "awaiting_acceptance"]);
2
+ export function detectDeliveryDuplicates(facts, intent) {
3
+ switch (intent.kind) {
4
+ case "create-work-item":
5
+ return detectWorkItemDuplicates(facts, intent.scope);
6
+ case "integration-start":
7
+ return detectIntegrationDuplicates(facts, intent);
8
+ case "review-request":
9
+ return detectReviewDuplicates(facts, intent);
10
+ case "complete-task":
11
+ return detectCompleteDuplicates(facts);
12
+ }
13
+ }
14
+ /**
15
+ * Apply the configured mode. `display` never interferes; `warn` reports every
16
+ * match as a warning; `enforce` hard-blocks on exact evidence and warns on
17
+ * suspected duplicates.
18
+ */
19
+ export function evaluateDeliveryGuard(duplicates, mode) {
20
+ if (mode === "display" || duplicates.length === 0) {
21
+ return { blocked: null, warnings: [] };
22
+ }
23
+ const exact = duplicates.filter((duplicate) => duplicate.severity === "exact");
24
+ const suspected = duplicates.filter((duplicate) => duplicate.severity === "suspected");
25
+ if (mode === "enforce" && exact.length > 0) {
26
+ return { blocked: exact[0], warnings: suspected };
27
+ }
28
+ return { blocked: null, warnings: [...exact, ...suspected] };
29
+ }
30
+ export function formatDeliveryDuplicate(duplicate) {
31
+ const refs = duplicate.refs.map((ref) => `${ref.kind} ${ref.id}`).join(", ");
32
+ const reuse = duplicate.reuseCommand === undefined
33
+ ? ""
34
+ : ` Existing proof: ${duplicate.reuseCommand}`;
35
+ return `${duplicate.severity === "exact" ? "Exact duplicate" : "Suspected duplicate"}: ${duplicate.reason} (${refs}).${reuse}`;
36
+ }
37
+ function detectWorkItemDuplicates(facts, scope) {
38
+ const wanted = normalizeScope(scope);
39
+ const duplicates = [];
40
+ for (const item of facts.workItems) {
41
+ const existing = normalizeScope({
42
+ title: item.title,
43
+ objective: item.objective,
44
+ acceptance: item.acceptance,
45
+ writeProjectIds: item.writeProjectIds
46
+ });
47
+ const sameScope = existing.title === wanted.title
48
+ && existing.objective === wanted.objective
49
+ && existing.acceptance === wanted.acceptance
50
+ && existing.writeProjectIds === wanted.writeProjectIds;
51
+ const ref = { kind: "work-item", id: item.id };
52
+ if (sameScope && OPEN_WORK_ITEM_STATUSES.has(item.status)) {
53
+ duplicates.push({
54
+ severity: "exact",
55
+ reason: `Work Item ${item.id} is already open with the identical scope`,
56
+ refs: [ref],
57
+ reuseCommand: `yui task work show ${facts.task.id}/${item.id}`
58
+ });
59
+ continue;
60
+ }
61
+ if (sameScope && item.status === "completed") {
62
+ duplicates.push({
63
+ severity: "suspected",
64
+ reason: `Work Item ${item.id} already delivered the identical scope; re-creating it may be a duplicate successor`,
65
+ refs: [ref],
66
+ reuseCommand: `yui task work show ${facts.task.id}/${item.id}`
67
+ });
68
+ continue;
69
+ }
70
+ if (!sameScope
71
+ && OPEN_WORK_ITEM_STATUSES.has(item.status)
72
+ && existing.writeProjectIds === wanted.writeProjectIds
73
+ && wanted.writeProjectIds.length > 0
74
+ && overlap(existing.acceptance, wanted.acceptance)) {
75
+ duplicates.push({
76
+ severity: "suspected",
77
+ reason: `Open Work Item ${item.id} shares the same Project scope and acceptance lines`,
78
+ refs: [ref]
79
+ });
80
+ }
81
+ }
82
+ return duplicates;
83
+ }
84
+ function detectIntegrationDuplicates(facts, intent) {
85
+ const wanted = new Set(intent.changeSetIds);
86
+ const duplicates = [];
87
+ for (const attempt of facts.integrations) {
88
+ if (attempt.projectId !== intent.projectId)
89
+ continue;
90
+ const existing = new Set(attempt.changeSetIds);
91
+ const sameSet = existing.size === wanted.size
92
+ && [...wanted].every((id) => existing.has(id));
93
+ const ref = { kind: "integration-attempt", id: attempt.id };
94
+ if (sameSet && attempt.status === "committed") {
95
+ duplicates.push({
96
+ severity: "exact",
97
+ reason: `Integration ${attempt.id} already committed this exact ChangeSet set`,
98
+ refs: [ref],
99
+ reuseCommand: `yui task integration show ${facts.task.id}/${attempt.id}`
100
+ });
101
+ continue;
102
+ }
103
+ if (sameSet
104
+ && (attempt.status === "running" || attempt.status === "validating")) {
105
+ duplicates.push({
106
+ severity: "suspected",
107
+ reason: `Integration ${attempt.id} is already ${attempt.status} for this exact ChangeSet set`,
108
+ refs: [ref],
109
+ reuseCommand: `yui task integration show ${facts.task.id}/${attempt.id}`
110
+ });
111
+ }
112
+ }
113
+ return duplicates;
114
+ }
115
+ function detectReviewDuplicates(facts, intent) {
116
+ const wanted = new Set(intent.taskCandidateCommits.map((commit) => commit.toLowerCase()));
117
+ const duplicates = [];
118
+ for (const round of facts.reviewRounds) {
119
+ if ((round.scope ?? "work-item") !== "task")
120
+ continue;
121
+ if (round.reviewerRoleName !== intent.reviewerRoleName)
122
+ continue;
123
+ const commits = new Set((round.taskCandidate?.projects ?? []).map((project) => project.commit.toLowerCase()));
124
+ const sameCandidate = commits.size === wanted.size
125
+ && commits.size > 0
126
+ && [...wanted].every((commit) => commits.has(commit));
127
+ if (!sameCandidate)
128
+ continue;
129
+ const ref = { kind: "review-round", id: round.id };
130
+ if (round.status === "completed") {
131
+ duplicates.push({
132
+ severity: "exact",
133
+ reason: `Task-final Review ${round.id} already attests this exact head`,
134
+ refs: [ref]
135
+ });
136
+ }
137
+ else if (round.status === "pending" || round.status === "running") {
138
+ duplicates.push({
139
+ severity: "suspected",
140
+ reason: `Task-final Review ${round.id} is already ${round.status} for this exact head`,
141
+ refs: [ref]
142
+ });
143
+ }
144
+ }
145
+ return duplicates;
146
+ }
147
+ function detectCompleteDuplicates(facts) {
148
+ if (facts.task.status === "completed" || facts.task.status === "archived") {
149
+ return [{
150
+ severity: "exact",
151
+ reason: `Task ${facts.task.id} is already ${facts.task.status}`,
152
+ refs: [{ kind: "task", id: facts.task.id }]
153
+ }];
154
+ }
155
+ return [];
156
+ }
157
+ function normalizeScope(scope) {
158
+ return {
159
+ title: scope.title.trim().toLowerCase(),
160
+ objective: scope.objective.trim().toLowerCase(),
161
+ acceptance: [...scope.acceptance]
162
+ .map((line) => line.trim().toLowerCase())
163
+ .filter((line) => line.length > 0)
164
+ .sort()
165
+ .join("\n"),
166
+ writeProjectIds: [...scope.writeProjectIds].map((id) => id.trim()).sort().join(",")
167
+ };
168
+ }
169
+ function overlap(left, right) {
170
+ const rightLines = new Set(right.split("\n"));
171
+ return left.split("\n").some((line) => line.length > 0 && rightLines.has(line));
172
+ }
173
+ /**
174
+ * Default number of consecutive yielded Leader turns that must produce no
175
+ * durable delivery change before the budget is exhausted.
176
+ */
177
+ export const DEFAULT_SEMANTIC_BUDGET_TURNS = 3;
178
+ /**
179
+ * Evaluate the semantic-progress budget from existing records only. The
180
+ * budget is exhausted when the last `turns` Leader Runs all yielded and no
181
+ * WorkItem/ChangeSet/Integration/Review record changed at or after the first
182
+ * of those Runs. Active execution (any Run) never exhausts the budget: a
183
+ * slow but progressing Worker or Leader is never interrupted.
184
+ */
185
+ export function evaluateSemanticBudget(facts, turns = DEFAULT_SEMANTIC_BUDGET_TURNS) {
186
+ if (facts.activeRuns.length > 0) {
187
+ return {
188
+ exhausted: false,
189
+ reason: "Active execution is in flight; the budget never interrupts a progressing Run.",
190
+ evidence: facts.activeRuns.map((run) => run.id)
191
+ };
192
+ }
193
+ const recentLeaderRuns = facts.leaderRuns
194
+ .filter((run) => run.status === "yielded")
195
+ .slice(-turns);
196
+ if (recentLeaderRuns.length < turns) {
197
+ return {
198
+ exhausted: false,
199
+ reason: `Fewer than ${turns} consecutive yielded Leader turns.`,
200
+ evidence: recentLeaderRuns.map((run) => run.id)
201
+ };
202
+ }
203
+ const firstStartedAt = Math.min(...recentLeaderRuns.map((run) => Date.parse(run.createdAt)));
204
+ const changed = latestDeliveryChangeAt(facts);
205
+ if (changed >= firstStartedAt) {
206
+ return {
207
+ exhausted: false,
208
+ reason: "A delivery record changed during the recent Leader turns.",
209
+ evidence: recentLeaderRuns.map((run) => run.id)
210
+ };
211
+ }
212
+ return {
213
+ exhausted: true,
214
+ reason: `${turns} consecutive Leader turns produced no durable delivery change; record a diagnosis/yield and wait for new facts instead of creating more records.`,
215
+ evidence: recentLeaderRuns.map((run) => run.id)
216
+ };
217
+ }
218
+ function latestDeliveryChangeAt(facts) {
219
+ const timestamps = [
220
+ ...facts.workItems.map((item) => Date.parse(item.updatedAt)),
221
+ ...facts.changeSets.map((changeSet) => Date.parse(changeSet.createdAt)),
222
+ ...facts.integrations.map((attempt) => Math.max(Date.parse(attempt.updatedAt), Date.parse(attempt.endedAt ?? attempt.updatedAt))),
223
+ ...facts.reviewRounds.map((round) => Math.max(Date.parse(round.createdAt), Date.parse(round.endedAt ?? round.createdAt)))
224
+ ];
225
+ return timestamps.length === 0 ? 0 : Math.max(...timestamps);
226
+ }