@zq-silk/yui 0.13.9 → 0.14.0
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/ARCHITECTURE.md +69 -428
- package/README.md +108 -298
- package/dist/agent/managedRuntimeEnvironment.js +2 -2
- package/dist/cli/commandCatalog.js +39 -77
- package/dist/cli/interactionCandidates.js +4 -4
- package/dist/cli/interactionPolicy.js +7 -10
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/updateCommand.js +6 -27
- package/dist/cli/updateOrchestrator.js +63 -484
- package/dist/cli/updatePorts.js +15 -333
- package/dist/cli/upgradeCommand.js +8 -65
- package/dist/cli.js +57 -242
- package/dist/commands/configCommands.js +11 -62
- package/dist/commands/executionAuditCommands.js +23 -23
- package/dist/commands/globalRoleCommands.js +2 -7
- package/dist/commands/jobCommands.js +1 -4
- package/dist/commands/projectCommands.js +5 -5
- package/dist/commands/releaseCommands.js +3 -10
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/sessionCommands.js +2 -2
- package/dist/commands/taskActor.js +31 -39
- package/dist/commands/taskChangeSetCommands.js +5 -12
- package/dist/commands/taskCommands.js +464 -1249
- package/dist/commands/taskContextCommand.js +35 -36
- package/dist/commands/taskExecutionCommands.js +33 -46
- package/dist/commands/taskInputCommands.js +20 -42
- package/dist/commands/taskNextActionCommand.js +9 -9
- package/dist/commands/taskOverviewCommand.js +56 -95
- package/dist/commands/taskRoleRuntimeStatus.js +77 -107
- package/dist/commands/taskUpstreamCommands.js +3 -3
- package/dist/commands/taskWorkspaceCommands.js +7 -79
- package/dist/commands/telemetryCommands.js +32 -124
- package/dist/commands/workflowCommands.js +3 -3
- package/dist/completion/fileCompletionManager.js +1 -1
- package/dist/config/configCatalog.js +4 -6
- package/dist/config/yuiConfig.js +6 -43
- package/dist/context/dispatchContext.js +14 -30
- package/dist/context/roleSessionContext.js +2 -2
- package/dist/context/sessionBootstrapManifest.js +2 -2
- package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
- package/dist/context/turnInputContract.js +204 -0
- package/dist/context/wakeNotification.js +2 -2
- package/dist/controller/agentRuntimeObserver.js +18 -18
- package/dist/controller/clientRuntime.js +13 -20
- package/dist/controller/controller.js +89 -116
- package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
- package/dist/controller/jobControl.js +17 -17
- package/dist/controller/resourceInventory.js +6 -6
- package/dist/controller/resourceInventoryLinux.js +38 -59
- package/dist/controller/resourceInventoryRpc.js +3 -3
- package/dist/controller/resourceInventoryWorker.js +1 -1
- package/dist/controller/runtime.js +46 -53
- package/dist/controller/runtimeEventInbox.js +23 -31
- package/dist/controller/runtimeEventProcessor.js +15 -15
- package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
- package/dist/controller/runtimeLaunchCoordinator.js +3 -3
- package/dist/controller/runtimeObservationHook.js +11 -8
- package/dist/controller/sessionNotify.js +11 -11
- package/dist/controller/structuredProviderObservation.js +89 -16
- package/dist/coordination/workMailbox.js +309 -579
- package/dist/coordination/workMailboxQueue.js +5 -6
- package/dist/core/controllerClient.js +1 -91
- package/dist/core/controllerServer.js +3 -6
- package/dist/doctor/doctor.js +51 -314
- package/dist/execution/candidateConvergence.js +3 -3
- package/dist/execution/executionGroup.js +32 -33
- package/dist/execution/executionHealth.js +36 -38
- package/dist/execution/resourceBroker.js +12 -12
- package/dist/executor/agentExecutor.js +30 -265
- package/dist/executor/effectiveLaunch.js +9 -19
- package/dist/executor/executorRegistry.js +43 -17
- package/dist/executor/fileRoleLaunchPlanner.js +56 -56
- package/dist/executor/launchPlan.js +3 -3
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +20 -25
- package/dist/input/inputRequest.js +12 -12
- package/dist/integration/changeSet.js +9 -13
- package/dist/integration/changeSetManifest.js +1 -1
- package/dist/integration/gitIntegrationService.js +2 -2
- package/dist/integration/integrationQueueService.js +5 -21
- package/dist/integration/overlapDiagnostics.js +2 -2
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/job/jobRunner.js +1 -1
- package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
- package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
- package/dist/message/message.js +6 -6
- package/dist/observability/executionAudit.js +74 -86
- package/dist/observability/faultClassification.js +7 -24
- package/dist/observability/orchestrationMetrics.js +5 -5
- package/dist/observability/runtimeIdentity.js +34 -101
- package/dist/profile/agentProfile.js +1 -1
- package/dist/release/cliHomeReleaseFence.js +3 -3
- package/dist/release/releaseWorkflowEngine.js +6 -10
- package/dist/release/releaseWorkflowPorts.js +2 -2
- package/dist/release/workflowFileLock.js +1 -1
- package/dist/repository/checkoutSwap.js +1 -1
- package/dist/repository/gitWorkspace.js +0 -13
- package/dist/repository/project.js +1 -1
- package/dist/repository/projectMaintenanceLock.js +1 -2
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +21 -25
- package/dist/repository/taskWorkspaceIdentity.js +8 -21
- package/dist/repository/taskWorkspacePreparer.js +63 -620
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +1 -1
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/sqliteResourceRegistry.js +1 -1
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewFindingLedger.js +1 -1
- package/dist/review/reviewOutcomeClassifier.js +35 -50
- package/dist/review/reviewRound.js +14 -25
- package/dist/review/reviewerAvailability.js +4 -4
- package/dist/review/taskFinalReviewContractResolution.js +41 -0
- package/dist/role/role.js +6 -3
- package/dist/runtime/agentDriver.js +4 -0
- package/dist/runtime/agentHost.js +151 -36
- package/dist/runtime/builtinAgentDrivers.js +79 -2
- package/dist/runtime/codexAppServerRuntime.js +122 -0
- package/dist/runtime/continuationManager.js +3 -5
- package/dist/runtime/exactControlPlane.js +17 -42
- package/dist/runtime/firstProgressAdvisory.js +1 -1
- package/dist/runtime/index.js +2 -2
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +4 -4
- package/dist/runtime/processExitObservation.js +1 -1
- package/dist/runtime/processExitOutbox.js +0 -32
- package/dist/runtime/promptEnvelope.js +9 -9
- package/dist/runtime/providerContinuation.js +2 -2
- package/dist/runtime/providerContinuationReconciliationService.js +2 -2
- package/dist/runtime/providerRuntimeIdentity.js +76 -24
- package/dist/runtime/recentTurnIds.js +38 -0
- package/dist/runtime/runtimeContinuationProjection.js +2 -2
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +58 -21
- package/dist/runtime/runtimeProjection.js +19 -27
- package/dist/runtime/sessionLaunchRequest.js +2 -2
- package/dist/runtime/structuredProviderHost.js +177 -12
- package/dist/runtime/tmuxAdapters.js +46 -11
- package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
- package/dist/scheduler/leaderWakeupProcessor.js +147 -445
- package/dist/scheduler/operatorEvent.js +4 -6
- package/dist/scheduler/resourceQueueProjection.js +71 -0
- package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
- package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
- package/dist/scheduler/taskExecutionProjection.js +99 -99
- package/dist/scheduler/taskObservabilityProjection.js +10 -10
- package/dist/scheduler/taskWake.js +4 -4
- package/dist/scheduler/wakeReason.js +6 -10
- package/dist/scheduler/wakeupQueue.js +0 -9
- package/dist/setup/setupCommand.js +2 -2
- package/dist/storage/currentTaskStore.js +46 -0
- package/dist/storage/persistenceWorker.js +1 -1
- package/dist/storage/sqliteSchema.js +81 -485
- package/dist/storage/sqliteStore.js +206 -365
- package/dist/storage/storageSchema.js +1 -15
- package/dist/storage/storageVersions.js +8 -9
- package/dist/storage/storeRpc.js +10 -34
- package/dist/storage/taskStore.js +63 -3415
- package/dist/storage/upgrade/recordVersions.js +55 -149
- package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
- package/dist/task/completionReadiness.js +5 -5
- package/dist/task/deliveryGuard.js +10 -10
- package/dist/task/nextAction.js +74 -77
- package/dist/task/task.js +2 -4
- package/dist/task/taskRecordReference.js +3 -3
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/telemetry/sqliteTelemetryStore.js +53 -53
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +8 -14
- package/dist/turn/turn.js +356 -0
- package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
- package/dist/verification/gateArtifactStore.js +2 -2
- package/dist/web/assets/client/app.js +1 -1
- package/dist/web/assets/client/components.js +29 -54
- package/dist/web/assets/client/i18n.js +17 -37
- package/dist/web/assets/client/view.js +37 -37
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +5 -5
- package/dist/web/assets/styles/widgets.js +1 -2
- package/dist/web/webSnapshot.js +65 -60
- package/dist/workItem/workItem.js +11 -11
- package/dist/workspace/workItemChangeSetManager.js +1 -1
- package/docs/task-local-identity.md +5 -5
- package/i18n/README.zh-CN.md +41 -54
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +85 -83
- package/skills/yui-operator/SKILL.md +16 -16
- package/skills/yui-reviewer/SKILL.md +10 -10
- package/skills/yui-runtime/SKILL.md +17 -18
- package/skills/yui-worker/SKILL.md +16 -18
- package/dist/context/runContextContract.js +0 -162
- package/dist/executor/turnCompletion.js +0 -126
- package/dist/review/taskFinalReviewContractEvent.js +0 -1
- package/dist/review/taskFinalReviewContractRebind.js +0 -367
- package/dist/run/agentRun.js +0 -356
- package/dist/run/rejectedYieldAttempt.js +0 -221
- package/dist/run/runControlRequest.js +0 -50
- package/dist/run/yieldReceipt.js +0 -65
- package/dist/runtime/turnCompletion.js +0 -3
- package/dist/scheduler/actionability.js +0 -323
- package/dist/scheduler/activeRoleRunDelivery.js +0 -868
- package/dist/scheduler/activeTaskProgress.js +0 -126
- package/dist/storage/compatibleTaskStore.js +0 -248
- package/dist/storage/migration/baseline.js +0 -78
- package/dist/storage/migration/classifier.js +0 -51
- package/dist/storage/migration/compatibleCodec.js +0 -53
- package/dist/storage/migration/engine.js +0 -147
- package/dist/storage/migration/index.js +0 -33
- package/dist/storage/migration/planner.js +0 -154
- package/dist/storage/migration/productionRegistry.js +0 -3931
- package/dist/storage/migration/registry.js +0 -169
- package/dist/storage/migration/report.js +0 -54
- package/dist/storage/migration/types.js +0 -31
- package/dist/storage/upgrade/homeClassification.js +0 -353
- package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
- package/dist/storage/upgrade/migrationReceipt.js +0 -67
- package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
- package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
- package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
- package/dist/storage/upgrade/recordVersionScan.js +0 -176
- package/dist/storage/upgrade/sqliteFileSet.js +0 -50
- package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
- package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
- package/dist/storage/upgrade/sqliteStateMigration.js +0 -918
- package/dist/storage/upgrade/switchProgress.js +0 -80
- package/dist/storage/upgrade/upgradeReceipt.js +0 -161
- package/dist/storage/upgradeCoordination.js +0 -187
- package/dist/storage/upgradeFence.js +0 -366
- package/dist/telemetry/telemetryCompaction.js +0 -252
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Read-only execution audit aggregator (Issue 11 §3).
|
|
3
3
|
*
|
|
4
4
|
* The audit answers "what happened in this Home" from durable records alone:
|
|
5
|
-
*
|
|
5
|
+
* Turns/failures/durations, wake reasons, Session generations, Review execution
|
|
6
6
|
* vs semantic failures, Integration failure classes and gate reuse, telemetry
|
|
7
7
|
* volume, and the longest/stale executions. It never writes Task state, never
|
|
8
8
|
* wakes a Leader, and never takes the storage write lock — it only calls the
|
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { readdirSync, statSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
|
-
import {
|
|
15
|
+
import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
|
|
16
16
|
import { resolveTaskStoreBackendForHome } from "../storage/sqliteStore.js";
|
|
17
17
|
import { runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
|
|
18
|
-
import {
|
|
18
|
+
import { classifyTurnFailure, classifyIntegrationAttempt, classifyReviewRound, countFaultClasses } from "./faultClassification.js";
|
|
19
19
|
import { RUNTIME_LAUNCH_KINDS, RUNTIME_LAUNCH_PHASES } from "../runtime/launchDiagnostics.js";
|
|
20
20
|
import { UNSUPPORTED } from "./runtimeIdentity.js";
|
|
21
21
|
import { projectTaskOrchestration } from "./orchestrationMetrics.js";
|
|
22
22
|
export function createProductionExecutionAuditPorts() {
|
|
23
23
|
return {
|
|
24
|
-
openStore: (home) =>
|
|
24
|
+
openStore: (home) => openCurrentTaskStore(home),
|
|
25
25
|
directorySize: (path) => directorySizeBytes(path)
|
|
26
26
|
};
|
|
27
27
|
}
|
|
@@ -86,10 +86,10 @@ function roleBucket(roleName) {
|
|
|
86
86
|
}
|
|
87
87
|
return "other";
|
|
88
88
|
}
|
|
89
|
-
function durationMs(
|
|
90
|
-
if (
|
|
89
|
+
function durationMs(turn) {
|
|
90
|
+
if (turn.result === undefined)
|
|
91
91
|
return 0;
|
|
92
|
-
return Math.max(0, Date.parse(
|
|
92
|
+
return Math.max(0, Date.parse(turn.result.completedAt) - Date.parse(turn.createdAt));
|
|
93
93
|
}
|
|
94
94
|
function emptyLaunchFailureCounts() {
|
|
95
95
|
const counts = {
|
|
@@ -116,35 +116,35 @@ function addLaunchFailureCounts(counts, summary) {
|
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
118
118
|
* Issue 09: classify a terminal Session (stopped/broken) by its relationship
|
|
119
|
-
* to the last
|
|
120
|
-
* that stops after its
|
|
119
|
+
* to the last Turn it carried. Turns and Sessions are separate axes: a Session
|
|
120
|
+
* that stops after its Turn completed is a post-completion stop, not a Turn
|
|
121
121
|
* failure. Correlation is by Role + Agent + Adapter (the durable identity a
|
|
122
|
-
*
|
|
122
|
+
* Turn and its Session share) and the Session's terminal update timestamp.
|
|
123
123
|
*/
|
|
124
|
-
function
|
|
124
|
+
function classifyTerminalSessionTurnRelation(turns, roleName, session, counts) {
|
|
125
125
|
const terminalAt = Date.parse(session.updatedAt);
|
|
126
|
-
const carried =
|
|
127
|
-
.filter((
|
|
128
|
-
&&
|
|
129
|
-
&&
|
|
130
|
-
&& Date.parse(
|
|
126
|
+
const carried = turns
|
|
127
|
+
.filter((turn) => (turn.roleName === roleName
|
|
128
|
+
&& turn.effective.agentId === session.agentId
|
|
129
|
+
&& turn.effective.adapterId === session.adapterId
|
|
130
|
+
&& Date.parse(turn.createdAt) <= terminalAt))
|
|
131
131
|
.sort((left, right) => Date.parse(right.createdAt) - Date.parse(left.createdAt));
|
|
132
|
-
const
|
|
133
|
-
if (
|
|
134
|
-
counts.
|
|
132
|
+
const lastTurn = carried[0];
|
|
133
|
+
if (lastTurn === undefined) {
|
|
134
|
+
counts.noTurn += 1;
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
-
if (
|
|
138
|
-
&&
|
|
139
|
-
&& Date.parse(
|
|
140
|
-
counts.
|
|
137
|
+
if (lastTurn.status === "completed"
|
|
138
|
+
&& lastTurn.result !== undefined
|
|
139
|
+
&& Date.parse(lastTurn.result.completedAt) <= terminalAt) {
|
|
140
|
+
counts.postTurnCompleted += 1;
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
|
-
if (
|
|
144
|
-
counts.
|
|
143
|
+
if (lastTurn.status === "failed") {
|
|
144
|
+
counts.turnFailed += 1;
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
counts.
|
|
147
|
+
counts.activeTurn += 1;
|
|
148
148
|
}
|
|
149
149
|
function ok(data) {
|
|
150
150
|
return { status: "ok", data };
|
|
@@ -156,7 +156,7 @@ function failed(error) {
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
*
|
|
159
|
+
* Execute the read-only audit. The store is opened once and only read methods are
|
|
160
160
|
* called; no transaction, no Event, no Message, no wake is produced.
|
|
161
161
|
*/
|
|
162
162
|
export function runExecutionAudit(home, options = {}, ports = createProductionExecutionAuditPorts()) {
|
|
@@ -178,7 +178,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
178
178
|
homeIdentity: UNSUPPORTED,
|
|
179
179
|
scope,
|
|
180
180
|
tasks: section,
|
|
181
|
-
|
|
181
|
+
turns: section,
|
|
182
182
|
wakes: section,
|
|
183
183
|
sessions: section,
|
|
184
184
|
reviews: section,
|
|
@@ -224,11 +224,11 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
224
224
|
return failed(error);
|
|
225
225
|
}
|
|
226
226
|
})();
|
|
227
|
-
const
|
|
227
|
+
const turns = (() => {
|
|
228
228
|
try {
|
|
229
229
|
let total = 0;
|
|
230
230
|
let active = 0;
|
|
231
|
-
let
|
|
231
|
+
let completed = 0;
|
|
232
232
|
let failedCount = 0;
|
|
233
233
|
let cumulativeDurationMs = 0;
|
|
234
234
|
let failedDurationMs = 0;
|
|
@@ -237,37 +237,37 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
237
237
|
const failures = [];
|
|
238
238
|
const launchFailures = emptyLaunchFailureCounts();
|
|
239
239
|
for (const taskId of taskIds) {
|
|
240
|
-
for (const
|
|
241
|
-
if (!inWindow(
|
|
240
|
+
for (const turn of store.listTurns(taskId)) {
|
|
241
|
+
if (!inWindow(turn.createdAt, options))
|
|
242
242
|
continue;
|
|
243
243
|
total += 1;
|
|
244
|
-
byRole[roleBucket(
|
|
245
|
-
if (
|
|
244
|
+
byRole[roleBucket(turn.roleName)] += 1;
|
|
245
|
+
if (turn.purpose === "review")
|
|
246
246
|
byPurpose.review += 1;
|
|
247
247
|
else
|
|
248
248
|
byPurpose.execution += 1;
|
|
249
|
-
const duration = durationMs(
|
|
250
|
-
if (
|
|
249
|
+
const duration = durationMs(turn);
|
|
250
|
+
if (turn.status === "active") {
|
|
251
251
|
active += 1;
|
|
252
|
-
cumulativeDurationMs += Math.max(0, Date.now() - Date.parse(
|
|
252
|
+
cumulativeDurationMs += Math.max(0, Date.now() - Date.parse(turn.createdAt));
|
|
253
253
|
}
|
|
254
|
-
else if (
|
|
255
|
-
|
|
254
|
+
else if (turn.status === "completed") {
|
|
255
|
+
completed += 1;
|
|
256
256
|
cumulativeDurationMs += duration;
|
|
257
257
|
}
|
|
258
|
-
else if (
|
|
258
|
+
else if (turn.status === "failed") {
|
|
259
259
|
failedCount += 1;
|
|
260
260
|
failedDurationMs += duration;
|
|
261
261
|
cumulativeDurationMs += duration;
|
|
262
|
-
addLaunchFailureCounts(launchFailures,
|
|
263
|
-
failures.push(
|
|
262
|
+
addLaunchFailureCounts(launchFailures, turn.result?.output);
|
|
263
|
+
failures.push(classifyTurnFailure(turn));
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
return ok({
|
|
268
268
|
total,
|
|
269
269
|
active,
|
|
270
|
-
|
|
270
|
+
completed,
|
|
271
271
|
failed: failedCount,
|
|
272
272
|
failureRate: total === 0 ? 0 : failedCount / total,
|
|
273
273
|
cumulativeDurationMs,
|
|
@@ -284,20 +284,18 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
284
284
|
})();
|
|
285
285
|
const wakes = (() => {
|
|
286
286
|
try {
|
|
287
|
-
let
|
|
287
|
+
let leaderTurns = 0;
|
|
288
288
|
let withWakeReasons = 0;
|
|
289
|
-
let orphanWakes = 0;
|
|
290
|
-
let orphanYieldOnly = 0;
|
|
291
289
|
let suppressedWakes = 0;
|
|
292
290
|
const byReason = new Map();
|
|
293
291
|
for (const taskId of taskIds) {
|
|
294
|
-
for (const
|
|
295
|
-
if (
|
|
292
|
+
for (const turn of store.listTurns(taskId)) {
|
|
293
|
+
if (turn.roleName !== "leader")
|
|
296
294
|
continue;
|
|
297
|
-
if (!inWindow(
|
|
295
|
+
if (!inWindow(turn.createdAt, options))
|
|
298
296
|
continue;
|
|
299
|
-
|
|
300
|
-
const match = WAKE_REASON_PATTERN.exec(
|
|
297
|
+
leaderTurns += 1;
|
|
298
|
+
const match = WAKE_REASON_PATTERN.exec(turn.inputs[0].input.directive ?? "");
|
|
301
299
|
if (match === null)
|
|
302
300
|
continue;
|
|
303
301
|
withWakeReasons += 1;
|
|
@@ -305,12 +303,6 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
305
303
|
for (const reason of reasons) {
|
|
306
304
|
byReason.set(reason, (byReason.get(reason) ?? 0) + 1);
|
|
307
305
|
}
|
|
308
|
-
if (classifyWakeReasons(reasons).faultClass
|
|
309
|
-
=== "scheduler-duplicate-suppressed-wake") {
|
|
310
|
-
orphanWakes += 1;
|
|
311
|
-
if (run.status === "yielded")
|
|
312
|
-
orphanYieldOnly += 1;
|
|
313
|
-
}
|
|
314
306
|
}
|
|
315
307
|
for (const event of store.listEvents(taskId)) {
|
|
316
308
|
if (event.type !== "wake.suppressed")
|
|
@@ -321,14 +313,12 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
321
313
|
}
|
|
322
314
|
}
|
|
323
315
|
return ok({
|
|
324
|
-
|
|
316
|
+
leaderTurns,
|
|
325
317
|
withWakeReasons,
|
|
326
|
-
orphanWakes,
|
|
327
|
-
orphanYieldOnly,
|
|
328
318
|
byReason: Object.fromEntries([...byReason.entries()].sort((left, right) => right[1] - left[1])),
|
|
329
319
|
// Scheduler single-flight suppression: wakes that were coalesced
|
|
330
320
|
// because the Role runtime lifecycle lane was busy. These are
|
|
331
|
-
// scheduler outcomes, never failed
|
|
321
|
+
// scheduler outcomes, never failed Turns.
|
|
332
322
|
suppressedWakes: { status: "ok", data: suppressedWakes }
|
|
333
323
|
});
|
|
334
324
|
}
|
|
@@ -346,14 +336,14 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
346
336
|
let conversationSwitches = 0;
|
|
347
337
|
let lifecycleEvents = 0;
|
|
348
338
|
let stopFailures = 0;
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
339
|
+
const terminalByTurnRelation = {
|
|
340
|
+
postTurnCompleted: 0,
|
|
341
|
+
turnFailed: 0,
|
|
342
|
+
activeTurn: 0,
|
|
343
|
+
noTurn: 0
|
|
354
344
|
};
|
|
355
345
|
for (const taskId of taskIds) {
|
|
356
|
-
const
|
|
346
|
+
const turns = store.listTurns(taskId);
|
|
357
347
|
for (const set of store.listRoleSessionSets(taskId)) {
|
|
358
348
|
const history = Array.isArray(set.history) ? set.history : [];
|
|
359
349
|
for (const session of [...history, ...Object.values(set.sessions)]) {
|
|
@@ -365,7 +355,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
365
355
|
else
|
|
366
356
|
other += 1;
|
|
367
357
|
if (session.status === "ended") {
|
|
368
|
-
|
|
358
|
+
classifyTerminalSessionTurnRelation(turns, set.owner.roleName, session, terminalByTurnRelation);
|
|
369
359
|
}
|
|
370
360
|
}
|
|
371
361
|
}
|
|
@@ -393,7 +383,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
393
383
|
conversationSwitches,
|
|
394
384
|
lifecycleEvents,
|
|
395
385
|
stopFailures,
|
|
396
|
-
|
|
386
|
+
terminalByTurnRelation
|
|
397
387
|
});
|
|
398
388
|
}
|
|
399
389
|
catch (error) {
|
|
@@ -602,7 +592,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
602
592
|
entries.push({
|
|
603
593
|
taskId,
|
|
604
594
|
eventId: event.id,
|
|
605
|
-
|
|
595
|
+
turnId: event.payload.turnId ?? "",
|
|
606
596
|
roleName: event.payload.roleName ?? "",
|
|
607
597
|
source: event.payload.source ?? "unknown",
|
|
608
598
|
phase: event.payload.phase ?? "unknown",
|
|
@@ -656,7 +646,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
656
646
|
return [];
|
|
657
647
|
return [projectTaskOrchestration({
|
|
658
648
|
task,
|
|
659
|
-
|
|
649
|
+
turns: withinWindow(store.listTurns(taskId), options),
|
|
660
650
|
roleSessionSets: sessionSetsWithinWindow(store.listRoleSessionSets(taskId), options),
|
|
661
651
|
workItems: withinWindow(store.listWorkItems(taskId), options),
|
|
662
652
|
changeSets: withinWindow(store.listChangeSets(taskId), options),
|
|
@@ -723,14 +713,12 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
723
713
|
let processExitObservations = 0;
|
|
724
714
|
let compactionEvents = 0;
|
|
725
715
|
for (const taskId of taskIds) {
|
|
726
|
-
for (const run of store.
|
|
716
|
+
for (const run of store.listTurns(taskId)) {
|
|
727
717
|
if (!inWindow(run.createdAt, options))
|
|
728
718
|
continue;
|
|
729
|
-
const version = String(run.effective.contextProtocolVersion
|
|
719
|
+
const version = String(run.effective.contextProtocolVersion);
|
|
730
720
|
protocolVersions.set(version, (protocolVersions.get(version) ?? 0) + 1);
|
|
731
|
-
|
|
732
|
-
manifestDigests.add(run.effective.sessionManifestCompatibilityDigest);
|
|
733
|
-
}
|
|
721
|
+
manifestDigests.add(run.effective.sessionManifestCompatibilityDigest);
|
|
734
722
|
}
|
|
735
723
|
for (const event of store.listEvents(taskId)) {
|
|
736
724
|
if (!inWindow(event.createdAt, options))
|
|
@@ -777,21 +765,21 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
777
765
|
try {
|
|
778
766
|
const entries = [];
|
|
779
767
|
for (const taskId of taskIds) {
|
|
780
|
-
for (const
|
|
781
|
-
if (!inWindow(
|
|
768
|
+
for (const turn of store.listTurns(taskId)) {
|
|
769
|
+
if (!inWindow(turn.createdAt, options))
|
|
782
770
|
continue;
|
|
783
|
-
const duration =
|
|
784
|
-
? Math.max(0, Date.now() - Date.parse(
|
|
785
|
-
: durationMs(
|
|
771
|
+
const duration = turn.status === "active"
|
|
772
|
+
? Math.max(0, Date.now() - Date.parse(turn.createdAt))
|
|
773
|
+
: durationMs(turn);
|
|
786
774
|
if (duration <= 0)
|
|
787
775
|
continue;
|
|
788
776
|
entries.push({
|
|
789
777
|
taskId,
|
|
790
|
-
|
|
791
|
-
roleName:
|
|
792
|
-
status:
|
|
778
|
+
turnId: turn.id,
|
|
779
|
+
roleName: turn.roleName,
|
|
780
|
+
status: turn.status,
|
|
793
781
|
durationMs: duration,
|
|
794
|
-
startedAt:
|
|
782
|
+
startedAt: turn.createdAt
|
|
795
783
|
});
|
|
796
784
|
}
|
|
797
785
|
}
|
|
@@ -809,7 +797,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
809
797
|
homeIdentity,
|
|
810
798
|
scope,
|
|
811
799
|
tasks,
|
|
812
|
-
|
|
800
|
+
turns,
|
|
813
801
|
wakes,
|
|
814
802
|
sessions,
|
|
815
803
|
reviews,
|
|
@@ -3,9 +3,8 @@ export const FAULT_CLASSES = [
|
|
|
3
3
|
"provider-transient",
|
|
4
4
|
"policy-denied",
|
|
5
5
|
"session-dead",
|
|
6
|
-
"delivery-
|
|
6
|
+
"delivery-uncertain",
|
|
7
7
|
"storage-backend-lock",
|
|
8
|
-
"scheduler-duplicate-suppressed-wake",
|
|
9
8
|
"review-infra",
|
|
10
9
|
"review-semantic-negative",
|
|
11
10
|
"integration-environment",
|
|
@@ -23,7 +22,7 @@ const PROVIDER_TRANSIENT_PATTERN = /\b5\d{2}\b|gateway time|connection lost|serv
|
|
|
23
22
|
const POLICY_DENIED_PATTERN = /policy|permission denied|forbidden|not authorized|\b403\b/iu;
|
|
24
23
|
const SESSION_DEAD_PATTERN = /tmux session exited|session cannot be replaced|could not start|pane[^\n]*(dead|exited)|session[^\n]*(dead|exited|broken)|native session|launch reservation/iu;
|
|
25
24
|
const STORAGE_LOCK_PATTERN = /storage lock|database is locked|SQLITE_BUSY|lock timeout|COMMAND_TIMED_OUT|storage conflict|timed out waiting/iu;
|
|
26
|
-
const DELIVERY_UNCERTAIN_PATTERN = /delivery[^\n]*(uncertain|unknown)|
|
|
25
|
+
const DELIVERY_UNCERTAIN_PATTERN = /delivery[^\n]*(uncertain|unknown)|uncertain[^\n]*delivery|push[^\n]*uncertain/iu;
|
|
27
26
|
const STALE_BASE_PATTERN = /stale (role|agent|base|target|state)|expected head|base[^\n]*(changed|moved)|conflict|CAS/iu;
|
|
28
27
|
const INTEGRATION_ENVIRONMENT_PATTERN = /tsc: not found|command not found|ENOENT|runner disappeared|runner vanished|dirty target|wrong argument|not a git repository|npm error|node: not found/iu;
|
|
29
28
|
function excerpt(text, max = 160) {
|
|
@@ -31,11 +30,11 @@ function excerpt(text, max = 160) {
|
|
|
31
30
|
return normalized.length <= max ? normalized : `${normalized.slice(0, max)}…`;
|
|
32
31
|
}
|
|
33
32
|
/**
|
|
34
|
-
* Classify a failed
|
|
33
|
+
* Classify a failed Turn. A structured hint (from a future capability
|
|
35
34
|
* provider) always wins; otherwise the summary is matched as historical
|
|
36
|
-
* import text.
|
|
35
|
+
* import text. Non-failed Turns return {@link NO_FAULT}.
|
|
37
36
|
*/
|
|
38
|
-
export function
|
|
37
|
+
export function classifyTurnFailure(run, structured) {
|
|
39
38
|
if (run.status !== "failed")
|
|
40
39
|
return NO_FAULT;
|
|
41
40
|
if (structured !== undefined) {
|
|
@@ -45,7 +44,7 @@ export function classifyAgentRunFailure(run, structured) {
|
|
|
45
44
|
evidence: structured.evidence
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
|
-
const summary = run.
|
|
47
|
+
const summary = run.result?.output ?? "";
|
|
49
48
|
if (summary.length === 0) {
|
|
50
49
|
return { faultClass: "other", basis: "text-historical", evidence: "" };
|
|
51
50
|
}
|
|
@@ -60,7 +59,7 @@ export function classifyAgentRunFailure(run, structured) {
|
|
|
60
59
|
return { faultClass: "storage-backend-lock", basis: "text-historical", evidence: text };
|
|
61
60
|
}
|
|
62
61
|
if (DELIVERY_UNCERTAIN_PATTERN.test(summary)) {
|
|
63
|
-
return { faultClass: "delivery-
|
|
62
|
+
return { faultClass: "delivery-uncertain", basis: "text-historical", evidence: text };
|
|
64
63
|
}
|
|
65
64
|
if (STALE_BASE_PATTERN.test(summary)) {
|
|
66
65
|
return { faultClass: "stale-base-target-cas", basis: "text-historical", evidence: text };
|
|
@@ -134,22 +133,6 @@ export function classifyIntegrationAttempt(attempt) {
|
|
|
134
133
|
evidence: "failed without checks or conflict"
|
|
135
134
|
};
|
|
136
135
|
}
|
|
137
|
-
/**
|
|
138
|
-
* Wake reason classification. An orphan wake (the scheduler re-woke a Leader
|
|
139
|
-
* with no new fact) is the duplicate/suppressed-wake class. Quiescence
|
|
140
|
-
* suppression counters are owned by the scheduler Issue; when absent the
|
|
141
|
-
* audit reports `unsupported` instead of guessing.
|
|
142
|
-
*/
|
|
143
|
-
export function classifyWakeReasons(reasons) {
|
|
144
|
-
if (reasons.some((reason) => reason === "task-orphaned")) {
|
|
145
|
-
return {
|
|
146
|
-
faultClass: "scheduler-duplicate-suppressed-wake",
|
|
147
|
-
basis: "structured",
|
|
148
|
-
evidence: reasons.join(",")
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
return NO_FAULT;
|
|
152
|
-
}
|
|
153
136
|
export function emptyFaultClassCounts() {
|
|
154
137
|
return Object.freeze(Object.fromEntries(FAULT_CLASSES.map((name) => [name, 0])));
|
|
155
138
|
}
|
|
@@ -4,7 +4,7 @@ import { projectFirstProgressAdvisory } from "../runtime/firstProgressAdvisory.j
|
|
|
4
4
|
/** One Task's orchestration cost and advisory projection, with no writes. */
|
|
5
5
|
export function projectTaskOrchestration(facts) {
|
|
6
6
|
const evidence = {
|
|
7
|
-
|
|
7
|
+
listTurns: () => facts.turns,
|
|
8
8
|
listReviewFindings: () => facts.reviewFindings,
|
|
9
9
|
listEvents: () => facts.events
|
|
10
10
|
};
|
|
@@ -57,10 +57,10 @@ export function projectTaskOrchestration(facts) {
|
|
|
57
57
|
timeToFirstProjectCommitMs: firstCommitAt === undefined
|
|
58
58
|
? null
|
|
59
59
|
: Math.max(0, Date.parse(firstCommitAt) - Date.parse(facts.task.createdAt)),
|
|
60
|
-
|
|
61
|
-
total: facts.
|
|
62
|
-
byStatus: counts(facts.
|
|
63
|
-
byRole: counts(facts.
|
|
60
|
+
turns: {
|
|
61
|
+
total: facts.turns.length,
|
|
62
|
+
byStatus: counts(facts.turns.map(({ status }) => status)),
|
|
63
|
+
byRole: counts(facts.turns.map(({ roleName }) => roleName))
|
|
64
64
|
},
|
|
65
65
|
workItems: facts.workItems.length,
|
|
66
66
|
reviews: {
|
|
@@ -14,7 +14,6 @@ import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from "n
|
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import Database from "better-sqlite3";
|
|
16
16
|
import { CURRENT_AGGREGATE_SCHEMA_VERSION, CURRENT_STORAGE_LAYOUT_VERSION } from "../storage/storageVersions.js";
|
|
17
|
-
import { resolveTaskStoreBackendForHome } from "../storage/sqliteStore.js";
|
|
18
17
|
import { resolveStoreWorkerEnabledForHome } from "../storage/storeRpc.js";
|
|
19
18
|
export const UNSUPPORTED = "unsupported";
|
|
20
19
|
/**
|
|
@@ -178,10 +177,8 @@ export function createProductionStorageIdentityPorts(env = process.env) {
|
|
|
178
177
|
};
|
|
179
178
|
}
|
|
180
179
|
/**
|
|
181
|
-
* Collect
|
|
182
|
-
*
|
|
183
|
-
* (state.json vs yui.db + WAL). Contradictions between the two are the
|
|
184
|
-
* pseudo-layout-7 class of failure and fail closed.
|
|
180
|
+
* Collect read-only evidence for the exact current SQLite contract. Old files
|
|
181
|
+
* are never treated as an alternate authority or a repair source.
|
|
185
182
|
*/
|
|
186
183
|
export function collectStorageIdentity(home, ports = createProductionStorageIdentityPorts()) {
|
|
187
184
|
const manifestPath = join(home, "schema.json");
|
|
@@ -201,10 +198,10 @@ export function collectStorageIdentity(home, ports = createProductionStorageIden
|
|
|
201
198
|
&& Number.isFinite(manifest.aggregateSchemaVersion)) {
|
|
202
199
|
aggregateSchemaVersion = manifest.aggregateSchemaVersion;
|
|
203
200
|
}
|
|
204
|
-
if (typeof logicalLayout
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
if (typeof logicalLayout !== "number"
|
|
202
|
+
|| typeof aggregateSchemaVersion !== "number"
|
|
203
|
+
|| logicalLayout !== CURRENT_STORAGE_LAYOUT_VERSION
|
|
204
|
+
|| aggregateSchemaVersion !== CURRENT_AGGREGATE_SCHEMA_VERSION) {
|
|
208
205
|
manifestStatus = "unsupported";
|
|
209
206
|
}
|
|
210
207
|
}
|
|
@@ -222,120 +219,57 @@ export function collectStorageIdentity(home, ports = createProductionStorageIden
|
|
|
222
219
|
const dbBytes = ports.fileSize(dbPath);
|
|
223
220
|
const walPresent = ports.exists(`${dbPath}-wal`);
|
|
224
221
|
const shmPresent = ports.exists(`${dbPath}-shm`);
|
|
225
|
-
const configuredBackend =
|
|
222
|
+
const configuredBackend = "sqlite";
|
|
226
223
|
const workerEnabled = resolveStoreWorkerEnabledForHome(home, ports.env);
|
|
227
224
|
const dbHealth = dbPresent ? ports.probeDatabaseHealth(dbPath) : null;
|
|
228
|
-
const hasMigrationReceipt = ports.exists(join(home, "migration-receipt.json"));
|
|
229
225
|
const findings = [];
|
|
230
|
-
|
|
231
|
-
// Pseudo-layout-7 is only repairable when state.json is a valid fallback.
|
|
232
|
-
const stateText = statePresent ? ports.readText(statePath) : null;
|
|
233
|
-
let stateReadable = false;
|
|
234
|
-
if (stateText !== null) {
|
|
235
|
-
try {
|
|
236
|
-
const parsed = JSON.parse(stateText);
|
|
237
|
-
stateReadable = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed);
|
|
238
|
-
}
|
|
239
|
-
catch {
|
|
240
|
-
stateReadable = false;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
const layout7 = manifestStatus === "current"
|
|
244
|
-
&& typeof logicalLayout === "number"
|
|
245
|
-
&& logicalLayout >= CURRENT_STORAGE_LAYOUT_VERSION;
|
|
246
|
-
if (layout7 && !dbPresent) {
|
|
247
|
-
if (stateReadable) {
|
|
248
|
-
// Pseudo-layout-7: manifest claims SQLite WAL but yui.db was never
|
|
249
|
-
// materialized. state.json is the readable fallback; `yui upgrade`
|
|
250
|
-
// rebuilds yui.db from it. This is the recognized NEEDS_STORAGE_REPAIR
|
|
251
|
-
// state, not a hard contradiction — the file store is legitimately
|
|
252
|
-
// serving until repair runs.
|
|
253
|
-
findings.push({
|
|
254
|
-
code: "pseudo-layout-7",
|
|
255
|
-
severity: "needs-repair",
|
|
256
|
-
message: `Manifest declares layout ${logicalLayout} (SQLite WAL) but `
|
|
257
|
-
+ `${dbPath} does not exist; state.json is the only authoritative `
|
|
258
|
-
+ "copy (pseudo-layout-7).",
|
|
259
|
-
remediation: "Run `yui upgrade` to rebuild yui.db from state.json."
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
findings.push({
|
|
264
|
-
code: "no-authoritative-backend",
|
|
265
|
-
severity: "contradiction",
|
|
266
|
-
message: `Manifest declares layout ${logicalLayout} but neither `
|
|
267
|
-
+ "yui.db nor a readable state.json exists; there is no "
|
|
268
|
-
+ "authoritative backend.",
|
|
269
|
-
remediation: "Restore one copy from a backup; do not guess which is newer."
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (dbPresent && dbHealth !== null && dbHealth !== "ok") {
|
|
226
|
+
if (manifestStatus === "current" && !dbPresent) {
|
|
274
227
|
findings.push({
|
|
275
|
-
code: "database-
|
|
228
|
+
code: "current-database-missing",
|
|
276
229
|
severity: "contradiction",
|
|
277
|
-
message: `
|
|
278
|
-
remediation: "
|
|
279
|
-
+ "it from state.json."
|
|
230
|
+
message: `The current storage contract requires ${dbPath}, but it is missing.`,
|
|
231
|
+
remediation: "Preserve this Home for diagnosis and initialize a new Home."
|
|
280
232
|
});
|
|
281
233
|
}
|
|
282
|
-
if (
|
|
234
|
+
if (manifestStatus === "unsupported") {
|
|
283
235
|
findings.push({
|
|
284
|
-
code: "
|
|
236
|
+
code: "unsupported-storage-contract",
|
|
285
237
|
severity: "contradiction",
|
|
286
|
-
message: "
|
|
287
|
-
|
|
288
|
-
remediation: "Restore one copy from a backup; do not guess which is newer."
|
|
238
|
+
message: "The Home does not match this release's exact storage contract.",
|
|
239
|
+
remediation: "Open it read-only with its original Yui version, then let the Operator recreate unfinished work in a new Home."
|
|
289
240
|
});
|
|
290
241
|
}
|
|
291
|
-
if (
|
|
242
|
+
if (manifestStatus === "invalid") {
|
|
292
243
|
findings.push({
|
|
293
|
-
code: "
|
|
244
|
+
code: "invalid-storage-manifest",
|
|
294
245
|
severity: "contradiction",
|
|
295
|
-
message: "
|
|
296
|
-
|
|
297
|
-
remediation: "Run `yui upgrade` to create yui.db, or unset "
|
|
298
|
-
+ "YUI_STORE_BACKEND to keep using the file store explicitly."
|
|
246
|
+
message: "schema.json is invalid.",
|
|
247
|
+
remediation: "Preserve this Home for diagnosis and initialize a new Home."
|
|
299
248
|
});
|
|
300
249
|
}
|
|
301
|
-
if (
|
|
302
|
-
&& dbPresent
|
|
303
|
-
&& manifestStatus === "current") {
|
|
250
|
+
if (dbPresent && dbHealth !== null && dbHealth !== "ok") {
|
|
304
251
|
findings.push({
|
|
305
|
-
code: "database-
|
|
306
|
-
severity: "
|
|
307
|
-
message:
|
|
308
|
-
|
|
309
|
-
remediation: "Unset YUI_STORE_BACKEND to let the Home manifest select "
|
|
310
|
-
+ "SQLite, or remove the stale yui.db."
|
|
252
|
+
code: "database-unhealthy",
|
|
253
|
+
severity: "contradiction",
|
|
254
|
+
message: `yui.db exists but failed integrity check (${dbHealth}).`,
|
|
255
|
+
remediation: "Preserve this Home for diagnosis and initialize a new Home."
|
|
311
256
|
});
|
|
312
257
|
}
|
|
313
|
-
|
|
314
|
-
if (rawWorkerFlag !== undefined
|
|
315
|
-
&& !workerEnabled
|
|
316
|
-
&& configuredBackend !== "sqlite") {
|
|
258
|
+
if (statePresent) {
|
|
317
259
|
findings.push({
|
|
318
|
-
code: "
|
|
260
|
+
code: "ignored-historical-store",
|
|
319
261
|
severity: "warning",
|
|
320
|
-
message:
|
|
321
|
-
|
|
322
|
-
remediation: "Set YUI_STORE_BACKEND=sqlite to activate the worker, or "
|
|
323
|
-
+ "unset YUI_STORE_WORKER."
|
|
262
|
+
message: "state.json is present but is not read or written by the current store.",
|
|
263
|
+
remediation: "Keep it only as read-only historical evidence or archive it outside the active Home."
|
|
324
264
|
});
|
|
325
265
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
// no-authoritative-backend above (the file store is just a fallback there).
|
|
329
|
-
if (configuredBackend === "file"
|
|
330
|
-
&& !statePresent
|
|
331
|
-
&& manifestStatus === "current"
|
|
332
|
-
&& !(typeof logicalLayout === "number" && logicalLayout >= CURRENT_STORAGE_LAYOUT_VERSION)) {
|
|
266
|
+
const rawWorkerFlag = ports.env.YUI_STORE_WORKER;
|
|
267
|
+
if (rawWorkerFlag !== undefined && !["0", "1", "false", "true"].includes(rawWorkerFlag.toLowerCase())) {
|
|
333
268
|
findings.push({
|
|
334
|
-
code: "
|
|
335
|
-
severity: "
|
|
336
|
-
message:
|
|
337
|
-
remediation: "
|
|
338
|
-
+ "migration to create yui.db."
|
|
269
|
+
code: "invalid-worker-flag",
|
|
270
|
+
severity: "warning",
|
|
271
|
+
message: `YUI_STORE_WORKER=${rawWorkerFlag} is invalid.`,
|
|
272
|
+
remediation: "Use 1/true, 0/false, or unset YUI_STORE_WORKER."
|
|
339
273
|
});
|
|
340
274
|
}
|
|
341
275
|
return {
|
|
@@ -356,7 +290,6 @@ export function collectStorageIdentity(home, ports = createProductionStorageIden
|
|
|
356
290
|
shm: shmPresent,
|
|
357
291
|
health: dbHealth ?? UNSUPPORTED
|
|
358
292
|
},
|
|
359
|
-
hasMigrationReceipt,
|
|
360
293
|
findings
|
|
361
294
|
};
|
|
362
295
|
}
|