@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,240 @@
1
+ import { createHash } from "node:crypto";
2
+ import { requireIdentity, requireText, requireTimestamp, normalizedUniqueText } from "../domain/validation.js";
3
+ import { validateTaskRecordReference } from "../task/taskRecordReference.js";
4
+ /** Dispositions that still block Task completion under `enforce`. */
5
+ export const BLOCKING_FINDING_DISPOSITIONS = [
6
+ "open",
7
+ "fixed-pending-review"
8
+ ];
9
+ /** Dispositions the Leader may set explicitly. */
10
+ export const LEADER_FINDING_DISPOSITIONS = [
11
+ "fixed-pending-review",
12
+ "verified-fixed",
13
+ "accepted-risk",
14
+ "not-actionable",
15
+ "superseded"
16
+ ];
17
+ /** Normalizes the severity vocabularies reviewers may use to P1/P2/P3. */
18
+ export function normalizeReviewFindingSeverity(value) {
19
+ if (typeof value !== "string")
20
+ throw new Error("Review finding severity is required.");
21
+ const normalized = value.trim().toLowerCase();
22
+ if (normalized === "p1" || normalized === "critical" || normalized === "blocker")
23
+ return "p1";
24
+ if (normalized === "p2" || normalized === "high" || normalized === "major")
25
+ return "p2";
26
+ if (normalized === "p3"
27
+ || normalized === "medium"
28
+ || normalized === "moderate"
29
+ || normalized === "low"
30
+ || normalized === "minor"
31
+ || normalized === "nit"
32
+ || normalized === "info"
33
+ || normalized === "style") {
34
+ return "p3";
35
+ }
36
+ throw new Error(`Review finding severity is invalid: ${String(value)}.`);
37
+ }
38
+ /**
39
+ * Derives the stable ledger key for one reported finding. The key is
40
+ * deterministic for the same invariant/path/symbol so a repeated finding in a
41
+ * later Round updates the existing record instead of creating a duplicate.
42
+ */
43
+ export function reviewFindingStableKey(input) {
44
+ const invariant = input.invariant.trim().toLowerCase();
45
+ const primaryPath = (input.primaryPath ?? "").trim().toLowerCase();
46
+ const primarySymbol = (input.primarySymbol ?? "").trim().toLowerCase();
47
+ const basis = [
48
+ invariant,
49
+ primaryPath,
50
+ primarySymbol
51
+ ].join("|");
52
+ // Reports without path/symbol provenance cannot safely collapse different
53
+ // titles under one invariant. Use the title as the fallback identity instead
54
+ // of merging every such finding into a single ledger record.
55
+ const material = primaryPath.length === 0 && primarySymbol.length === 0
56
+ ? `${invariant}|${input.title.trim().toLowerCase()}`
57
+ : basis;
58
+ return `rf-${createHash("sha256").update(material).digest("hex").slice(0, 16)}`;
59
+ }
60
+ export function createReviewFinding(id, taskId, input, now) {
61
+ const timestamp = now.toISOString();
62
+ return validateReviewFinding({
63
+ schemaVersion: 1,
64
+ id: requireIdentity(id, "ReviewFinding id"),
65
+ taskId: requireIdentity(taskId, "Task id"),
66
+ ...(input.sourceId === undefined ? {} : { sourceId: requireIdentity(input.sourceId, "ReviewFinding source id") }),
67
+ stableKey: requireIdentity(input.stableKey, "ReviewFinding stable key"),
68
+ severity: input.severity,
69
+ invariant: requireText(input.invariant, "ReviewFinding invariant"),
70
+ title: requireText(input.title, "ReviewFinding title"),
71
+ affectedPaths: normalizedUniqueText(input.affectedPaths ?? [], "ReviewFinding affected path"),
72
+ affectedSymbols: normalizedUniqueText(input.affectedSymbols ?? [], "ReviewFinding affected symbol"),
73
+ evidence: normalizedUniqueText(input.evidence ?? [], "ReviewFinding evidence"),
74
+ firstReviewRoundId: requireIdentity(input.reviewRoundId, "ReviewFinding first ReviewRound"),
75
+ lastReviewRoundId: requireIdentity(input.reviewRoundId, "ReviewFinding last ReviewRound"),
76
+ disposition: "open",
77
+ createdAt: timestamp,
78
+ updatedAt: timestamp
79
+ });
80
+ }
81
+ /**
82
+ * Applies one Leader disposition. Terminal dispositions
83
+ * (verified-fixed/accepted-risk/not-actionable/superseded) are explicit Leader
84
+ * decisions and stay terminal; `fixed-pending-review` may still regress to
85
+ * `open` when a later Round reproduces the finding.
86
+ */
87
+ export function disposeReviewFinding(finding, input) {
88
+ validateReviewFinding(finding);
89
+ if (!LEADER_FINDING_DISPOSITIONS.includes(input.disposition)) {
90
+ throw new Error(`ReviewFinding disposition is not a Leader decision: ${input.disposition}.`);
91
+ }
92
+ if (finding.disposition !== "open" && finding.disposition !== "fixed-pending-review") {
93
+ throw new Error(`ReviewFinding ${finding.id} is already terminal: ${finding.disposition}.`);
94
+ }
95
+ if (input.disposition === "superseded" && input.supersededBy === undefined) {
96
+ throw new Error(`ReviewFinding ${finding.id} supersession requires a successor stable key.`);
97
+ }
98
+ const repair = input.repair === undefined
99
+ ? finding.repair
100
+ : validateReviewFindingRepair(input.repair);
101
+ return validateReviewFinding({
102
+ ...finding,
103
+ disposition: input.disposition,
104
+ ...(repair === undefined ? {} : { repair }),
105
+ dispositionBy: requireIdentity(input.by, "ReviewFinding disposition actor"),
106
+ ...(input.note === undefined ? {} : { dispositionNote: requireText(input.note, "ReviewFinding disposition note") }),
107
+ ...(input.supersededBy === undefined ? {} : { supersededBy: requireIdentity(input.supersededBy, "ReviewFinding successor stable key") }),
108
+ mergeRequired: false,
109
+ updatedAt: input.now.toISOString()
110
+ });
111
+ }
112
+ /**
113
+ * Reconciles a re-detection of this finding in a later Round. A regression
114
+ * reopens a `fixed-pending-review` finding; a `verified-fixed` finding that
115
+ * reproduces also reopens (the fix did not hold). Explicit Leader decisions
116
+ * (accepted-risk/not-actionable/superseded) stay terminal but still get their
117
+ * evidence and last-Round pointer refreshed.
118
+ */
119
+ export function redetectReviewFinding(finding, input) {
120
+ validateReviewFinding(finding);
121
+ const evidence = normalizedUniqueText([...finding.evidence, ...(input.evidence ?? [])], "ReviewFinding evidence");
122
+ const reopen = finding.disposition === "fixed-pending-review"
123
+ || finding.disposition === "verified-fixed";
124
+ return validateReviewFinding({
125
+ ...finding,
126
+ lastReviewRoundId: requireIdentity(input.reviewRoundId, "ReviewFinding last ReviewRound"),
127
+ evidence,
128
+ ...(reopen ? { disposition: "open", repair: undefined } : {}),
129
+ ...(reopen ? { mergeRequired: finding.mergeRequired } : {}),
130
+ updatedAt: input.now.toISOString()
131
+ });
132
+ }
133
+ /** Refreshes last-Round/evidence for a terminal finding without reopening it. */
134
+ export function touchReviewFinding(finding, input) {
135
+ validateReviewFinding(finding);
136
+ const evidence = normalizedUniqueText([...finding.evidence, ...(input.evidence ?? [])], "ReviewFinding evidence");
137
+ if (finding.lastReviewRoundId === input.reviewRoundId
138
+ && evidence.length === finding.evidence.length) {
139
+ return finding;
140
+ }
141
+ return validateReviewFinding({
142
+ ...finding,
143
+ lastReviewRoundId: requireIdentity(input.reviewRoundId, "ReviewFinding last ReviewRound"),
144
+ evidence,
145
+ updatedAt: input.now.toISOString()
146
+ });
147
+ }
148
+ /**
149
+ * Issue 06: a Reviewer reports a previously-open finding as resolved in a
150
+ * later semantic Round. The claim is only accepted when the ledger already
151
+ * has repair refs; otherwise the old finding remains open (a changed candidate
152
+ * without repair evidence must not advance disposition). With repair refs,
153
+ * this transitions `open` to `fixed-pending-review` (the fix claim is recorded
154
+ * but the Leader still owns the final disposition) and refreshes
155
+ * evidence/last-Round for `fixed-pending-review`. Explicit Leader decisions
156
+ * (accepted-risk/not-actionable/superseded) and `verified-fixed` are untouched.
157
+ */
158
+ export function resolveReviewFinding(finding, input) {
159
+ validateReviewFinding(finding);
160
+ const evidence = normalizedUniqueText([...finding.evidence, ...(input.evidence ?? [])], "ReviewFinding evidence");
161
+ const transition = finding.disposition === "open" && finding.repair !== undefined;
162
+ if (!transition
163
+ && finding.lastReviewRoundId === input.reviewRoundId
164
+ && evidence.length === finding.evidence.length) {
165
+ return finding;
166
+ }
167
+ return validateReviewFinding({
168
+ ...finding,
169
+ lastReviewRoundId: requireIdentity(input.reviewRoundId, "ReviewFinding last ReviewRound"),
170
+ evidence,
171
+ ...(transition ? { disposition: "fixed-pending-review" } : {}),
172
+ updatedAt: input.now.toISOString()
173
+ });
174
+ }
175
+ export function isReviewFindingBlocking(finding) {
176
+ return BLOCKING_FINDING_DISPOSITIONS.includes(finding.disposition)
177
+ && (finding.severity === "p1" || finding.severity === "p2");
178
+ }
179
+ export function validateReviewFinding(finding) {
180
+ if (finding.schemaVersion !== 1) {
181
+ throw new Error("ReviewFinding must use schemaVersion 1.");
182
+ }
183
+ validateTaskRecordReference({ taskId: finding.taskId, localId: finding.id }, "reviewFinding");
184
+ requireIdentity(finding.stableKey, "ReviewFinding stable key");
185
+ if (finding.severity !== "p1" && finding.severity !== "p2" && finding.severity !== "p3") {
186
+ throw new Error(`ReviewFinding severity is invalid: ${String(finding.severity)}.`);
187
+ }
188
+ requireText(finding.invariant, "ReviewFinding invariant");
189
+ requireText(finding.title, "ReviewFinding title");
190
+ normalizedUniqueText(finding.affectedPaths, "ReviewFinding affected path");
191
+ normalizedUniqueText(finding.affectedSymbols, "ReviewFinding affected symbol");
192
+ normalizedUniqueText(finding.evidence, "ReviewFinding evidence");
193
+ validateTaskRecordReference({ taskId: finding.taskId, localId: finding.firstReviewRoundId }, "reviewRound");
194
+ validateTaskRecordReference({ taskId: finding.taskId, localId: finding.lastReviewRoundId }, "reviewRound");
195
+ if (![
196
+ "open",
197
+ "fixed-pending-review",
198
+ "verified-fixed",
199
+ "accepted-risk",
200
+ "not-actionable",
201
+ "superseded"
202
+ ].includes(finding.disposition)) {
203
+ throw new Error(`ReviewFinding disposition is invalid: ${String(finding.disposition)}.`);
204
+ }
205
+ if (finding.repair !== undefined)
206
+ validateReviewFindingRepair(finding.repair);
207
+ if (finding.dispositionBy !== undefined) {
208
+ requireIdentity(finding.dispositionBy, "ReviewFinding disposition actor");
209
+ }
210
+ if (finding.dispositionNote !== undefined) {
211
+ requireText(finding.dispositionNote, "ReviewFinding disposition note");
212
+ }
213
+ if (finding.supersededBy !== undefined) {
214
+ requireIdentity(finding.supersededBy, "ReviewFinding successor stable key");
215
+ if (finding.disposition !== "superseded") {
216
+ throw new Error(`ReviewFinding ${finding.id} carries a successor but is not superseded.`);
217
+ }
218
+ }
219
+ if (finding.disposition === "superseded" && finding.supersededBy === undefined) {
220
+ throw new Error(`ReviewFinding ${finding.id} is superseded without a successor.`);
221
+ }
222
+ requireTimestamp(finding.createdAt, "ReviewFinding createdAt");
223
+ requireTimestamp(finding.updatedAt, "ReviewFinding updatedAt");
224
+ return finding;
225
+ }
226
+ function validateReviewFindingRepair(repair) {
227
+ if (repair.workItemId !== undefined) {
228
+ requireIdentity(repair.workItemId, "ReviewFinding repair WorkItem");
229
+ }
230
+ if (repair.commit !== undefined) {
231
+ const commit = requireText(repair.commit, "ReviewFinding repair commit").toLowerCase();
232
+ if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u.test(commit)) {
233
+ throw new Error("ReviewFinding repair commit is invalid.");
234
+ }
235
+ }
236
+ if (repair.verification !== undefined) {
237
+ requireText(repair.verification, "ReviewFinding repair verification");
238
+ }
239
+ return repair;
240
+ }