@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.
- package/README.md +5 -5
- package/dist/agent/managedRuntimeEnvironment.js +2 -1
- package/dist/cli/commandCatalog.js +251 -13
- package/dist/cli/updateOrchestrator.js +8 -0
- package/dist/cli/updatePorts.js +76 -22
- package/dist/cli.js +264 -20
- package/dist/commands/configCommands.js +83 -9
- package/dist/commands/controllerCommands.js +103 -0
- package/dist/commands/deliveryGuardPreflight.js +30 -0
- package/dist/commands/durableJobCommands.js +231 -0
- package/dist/commands/executionAuditCommands.js +193 -0
- package/dist/commands/grantCommands.js +374 -0
- package/dist/commands/projectCommands.js +119 -81
- package/dist/commands/releaseCommands.js +444 -0
- package/dist/commands/resourcesCommands.js +274 -0
- package/dist/commands/sessionCommands.js +104 -0
- package/dist/commands/taskActor.js +117 -0
- package/dist/commands/taskChangeSetCommands.js +60 -0
- package/dist/commands/taskCommands.js +618 -202
- package/dist/commands/taskCompletionGate.js +78 -1
- package/dist/commands/taskContextCommand.js +33 -6
- package/dist/commands/taskInputCommands.js +1 -1
- package/dist/commands/taskIntegrationCommands.js +136 -33
- package/dist/commands/taskIntegrationQueueCommands.js +228 -0
- package/dist/commands/taskNextActionCommand.js +100 -0
- package/dist/commands/taskOverlapCommands.js +120 -0
- package/dist/commands/taskOverviewCommand.js +36 -8
- package/dist/commands/telemetryCommands.js +330 -0
- package/dist/commands/workflowCommands.js +415 -0
- package/dist/config/yuiConfig.js +62 -0
- package/dist/controller/clientRuntime.js +42 -1
- package/dist/controller/controller.js +402 -56
- package/dist/controller/controllerMain.js +25 -2
- package/dist/controller/domainIdentity.js +16 -8
- package/dist/controller/fileSchedulerStoreAdapter.js +423 -31
- package/dist/controller/handoverCandidate.js +168 -0
- package/dist/controller/jobClient.js +102 -0
- package/dist/controller/jobControl.js +613 -0
- package/dist/controller/jobSupervisor.js +498 -0
- package/dist/controller/providerHookRunFence.js +34 -5
- package/dist/controller/resourceCleanupLinux.js +18 -9
- package/dist/controller/resourceInventoryLinux.js +90 -39
- package/dist/controller/runtime.js +165 -15
- package/dist/controller/runtimeEventInbox.js +234 -57
- package/dist/controller/runtimeEventProcessor.js +297 -58
- package/dist/controller/sessionOwnerReconciliation.js +321 -0
- package/dist/core/controllerServer.js +416 -27
- package/dist/core/controllerTelemetry.js +167 -0
- package/dist/doctor/doctor.js +113 -16
- package/dist/domain/validation.js +9 -0
- package/dist/execution/executionGroup.js +40 -3
- package/dist/executor/agentExecutor.js +6 -3
- package/dist/executor/effectiveLaunch.js +52 -0
- package/dist/executor/executorRegistry.js +50 -0
- package/dist/executor/fileRoleLaunchPlanner.js +61 -6
- package/dist/grant/capabilityGrant.js +282 -0
- package/dist/integration/changeSet.js +16 -3
- package/dist/integration/changeSetManifest.js +46 -0
- package/dist/integration/gitIntegrationService.js +528 -147
- package/dist/integration/integrationAttempt.js +54 -5
- package/dist/integration/integrationQueueEntry.js +221 -0
- package/dist/integration/integrationQueueService.js +955 -0
- package/dist/integration/manifestTags.js +99 -0
- package/dist/integration/overlapDiagnostics.js +211 -0
- package/dist/job/durableJob.js +449 -0
- package/dist/job/jobRunner.js +350 -0
- package/dist/lifecycle/exactRunTerminalization.js +24 -2
- package/dist/lifecycle/providerErrorClass.js +126 -0
- package/dist/message/message.js +16 -3
- package/dist/observability/executionAudit.js +545 -0
- package/dist/observability/faultClassification.js +160 -0
- package/dist/observability/runtimeIdentity.js +367 -0
- package/dist/release/fakeReleasePorts.js +55 -0
- package/dist/release/releaseHandover.js +475 -0
- package/dist/release/releaseIdempotencyStore.js +165 -0
- package/dist/release/releaseWorkflow.js +459 -0
- package/dist/release/releaseWorkflowEngine.js +688 -0
- package/dist/release/releaseWorkflowPorts.js +1720 -0
- package/dist/release/runtimeRelease.js +495 -0
- package/dist/release/workflowFileLock.js +218 -0
- package/dist/repository/gitWorkspace.js +177 -1
- package/dist/repository/projectMaintenanceLock.js +315 -0
- package/dist/repository/taskWorkspaceCoordinator.js +87 -17
- package/dist/repository/taskWorkspacePreparer.js +1091 -517
- package/dist/resources/autoResourceGc.js +116 -0
- package/dist/resources/liveReferences.js +574 -0
- package/dist/resources/resourceDiscovery.js +477 -0
- package/dist/resources/resourceGc.js +645 -0
- package/dist/resources/resourceRegistrar.js +256 -0
- package/dist/resources/resourceRegistry.js +150 -0
- package/dist/resources/resourceRegistryStore.js +41 -0
- package/dist/resources/resourceTypes.js +42 -0
- package/dist/resources/sqliteResourceRegistry.js +111 -0
- package/dist/review/reviewConfig.js +10 -0
- package/dist/review/reviewFinding.js +240 -0
- package/dist/review/reviewFindingLedger.js +545 -0
- package/dist/review/reviewOutcomeClassifier.js +61 -0
- package/dist/review/reviewRound.js +56 -4
- package/dist/run/agentRun.js +80 -4
- package/dist/run/providerRetry.js +84 -0
- package/dist/run/providerRetryConfig.js +63 -0
- package/dist/run/yieldReceipt.js +65 -0
- package/dist/runtime/exactControlPlane.js +79 -2
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/sessionOwnerIdentity.js +269 -0
- package/dist/runtime/sessionOwnerRegistry.js +132 -0
- package/dist/runtime/sessionReconciliation.js +93 -0
- package/dist/runtime/sessionTerminationGuard.js +211 -0
- package/dist/runtime/taskRuntimeIsolation.js +13 -0
- package/dist/runtime/tmuxAdapters.js +34 -1
- package/dist/scheduler/actionability.js +155 -0
- package/dist/scheduler/activeRoleRunDelivery.js +14 -5
- package/dist/scheduler/activeTaskProgress.js +60 -0
- package/dist/scheduler/leaderWakeupProcessor.js +22 -11
- package/dist/scheduler/roleRunStall.js +135 -29
- package/dist/scheduler/taskExecutionProjection.js +11 -0
- package/dist/storage/compatibleTaskStore.js +112 -5
- package/dist/storage/migration/productionRegistry.js +736 -1
- package/dist/storage/sqliteSchema.js +264 -3
- package/dist/storage/sqliteStore.js +487 -13
- package/dist/storage/storeRpc.js +21 -0
- package/dist/storage/taskStore.js +974 -21
- package/dist/storage/upgrade/homeClassification.js +120 -2
- package/dist/storage/upgrade/migrationReceipt.js +67 -0
- package/dist/storage/upgrade/pseudoLayoutRepair.js +241 -0
- package/dist/storage/upgrade/recordVersions.js +10 -1
- package/dist/storage/upgrade/sqliteMigrationTarget.js +58 -6
- package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +290 -0
- package/dist/storage/upgrade/sqliteStateMigration.js +258 -2
- package/dist/storage/upgrade/upgradeOrchestrator.js +482 -16
- package/dist/task/deliveryGuard.js +226 -0
- package/dist/task/nextAction.js +738 -0
- package/dist/task/repairWave.js +137 -0
- package/dist/task/taskRecordReference.js +6 -1
- package/dist/telemetry/sqliteTelemetryStore.js +387 -0
- package/dist/telemetry/telemetryCompaction.js +251 -0
- package/dist/telemetry/telemetryConfig.js +64 -0
- package/dist/telemetry/telemetryRouter.js +32 -0
- package/dist/telemetry/telemetryStore.js +19 -0
- package/dist/telemetry/telemetryWiring.js +33 -0
- package/dist/tmux/tmuxManager.js +20 -1
- package/dist/tmux/tmuxSocketEndpoint.js +20 -0
- package/dist/verification/gateArtifact.js +216 -0
- package/dist/verification/gateArtifactStore.js +87 -0
- package/dist/verification/verificationGateService.js +414 -0
- package/dist/verification/verificationPlan.js +308 -0
- package/dist/workspace/gitChangeSetCapture.js +12 -2
- package/dist/workspace/workItemChangeSetManager.js +60 -3
- package/package.json +1 -1
- 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
|
+
}
|