@zq-silk/yui 0.8.2 → 0.8.6
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 +40 -22
- package/README.md +61 -9
- package/dist/cli/commandCatalog.js +31 -14
- package/dist/cli/operatorWizard.js +10 -20
- package/dist/cli.js +187 -22
- package/dist/commands/executionAuditCommands.js +30 -0
- package/dist/commands/operatorCommands.js +42 -1
- package/dist/commands/taskCommands.js +648 -74
- package/dist/commands/taskCompletionGate.js +166 -2
- package/dist/commands/taskContextCommand.js +6 -1
- package/dist/commands/taskInputCommands.js +48 -10
- package/dist/commands/taskNextActionCommand.js +36 -3
- package/dist/context/runContextPack.js +19 -4
- package/dist/context/sessionBootstrapManifest.js +83 -2
- package/dist/controller/clientRuntime.js +7 -7
- package/dist/controller/controller.js +16 -8
- package/dist/controller/fileSchedulerStoreAdapter.js +64 -5
- package/dist/controller/handoverCandidate.js +10 -3
- package/dist/controller/sessionNotify.js +4 -22
- package/dist/executor/agentAdapter.js +2 -2
- package/dist/executor/agentExecutor.js +25 -5
- package/dist/executor/fileRoleLaunchPlanner.js +16 -11
- package/dist/integration/gitIntegrationService.js +50 -2
- package/dist/integration/integrationCheckEvidenceReuse.js +53 -0
- package/dist/observability/executionAudit.js +47 -1
- package/dist/observability/faultClassification.js +6 -4
- package/dist/observability/orchestrationMetrics.js +196 -0
- package/dist/operator/operatorSessionHistory.js +36 -0
- package/dist/release/releaseHandover.js +7 -5
- package/dist/release/runtimeRelease.js +15 -0
- package/dist/repository/gitWorkspace.js +7 -4
- package/dist/repository/taskBaseFreshness.js +4 -2
- package/dist/repository/taskWorkspaceCoordinator.js +13 -10
- package/dist/review/deltaRecheck.js +3 -2
- package/dist/review/reviewFindingLedger.js +5 -4
- package/dist/review/reviewOutcomeClassifier.js +252 -54
- package/dist/review/taskFinalReviewContractEvent.js +1 -0
- package/dist/review/taskFinalReviewContractRebind.js +350 -0
- package/dist/run/agentRun.js +2 -2
- package/dist/run/runIdentity.js +10 -70
- package/dist/runtime/agentHost.js +3 -4
- package/dist/runtime/codexAppServerRuntime.js +6 -0
- package/dist/runtime/firstProgressStopLoss.js +52 -0
- package/dist/runtime/launchBroker.js +10 -2
- package/dist/runtime/runtimeDeadlines.js +14 -0
- package/dist/runtime/sessionTitle.js +24 -12
- package/dist/runtime/structuredProviderHost.js +7 -1
- package/dist/runtime/tmuxAdapters.js +10 -3
- package/dist/scheduler/activeRoleRunDelivery.js +20 -18
- package/dist/scheduler/leaderWakeupProcessor.js +33 -2
- package/dist/scheduler/wakeReason.js +2 -0
- package/dist/storage/sqliteStore.js +10 -1
- package/dist/storage/taskStore.js +12 -1
- package/dist/task/completionReadiness.js +91 -19
- package/dist/task/deliveryGuard.js +3 -1
- package/dist/task/nextAction.js +146 -51
- package/dist/task/publicationReference.js +1 -0
- package/dist/task/repairWave.js +14 -1
- package/dist/task/task.js +10 -0
- package/dist/web/webSnapshot.js +7 -1
- package/dist/workItem/workItem.js +12 -0
- package/dist/workspace/workItemChangeSetManager.js +2 -1
- package/i18n/README.zh-CN.md +28 -8
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +79 -32
- package/skills/yui-operator/SKILL.md +51 -10
- package/skills/yui-reviewer/SKILL.md +23 -0
- package/skills/yui-runtime/SKILL.md +7 -2
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
-
import { resolve } from "node:path";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { isDeepStrictEqual } from "node:util";
|
|
@@ -36,8 +36,9 @@ import { runResourcesCommand } from "./commands/resourcesCommands.js";
|
|
|
36
36
|
import { applyOperatorSessionControl, runOperatorCommand } from "./commands/operatorCommands.js";
|
|
37
37
|
import { runProjectCommand } from "./commands/projectCommands.js";
|
|
38
38
|
import { runProfileCommand } from "./commands/profileCommands.js";
|
|
39
|
-
import { dispatchPreparedReviewRound, failPendingReviewRound, RESUMED_PENDING_FINAL_REVIEW, TERMINALIZED_LEADER_BEFORE_FINAL_REVIEW, TaskFinalReviewDispatchDriftError, preserveReviewRoundWorkspace, parseTaskCompletionRequest, preflightTaskCompletion, runTaskCommand, normalizedExecutionLanePlan, validateTaskArchiveRequest } from "./commands/taskCommands.js";
|
|
39
|
+
import { dispatchPreparedReviewRound, failPendingReviewRound, RESUMED_PENDING_FINAL_REVIEW, TERMINALIZED_LEADER_BEFORE_FINAL_REVIEW, TaskFinalReviewDispatchDriftError, preserveReviewRoundWorkspace, parseTaskCompletionRequest, parseTaskFinalReviewContractRebindRequest, preflightTaskCompletion, runTaskCommand, normalizedExecutionLanePlan, validateTaskArchiveRequest } from "./commands/taskCommands.js";
|
|
40
40
|
import { taskActor } from "./commands/taskActor.js";
|
|
41
|
+
import { isCurrentGlobalOperator } from "./commands/taskInputCommands.js";
|
|
41
42
|
import { runTaskIntegrationCommand } from "./commands/taskIntegrationCommands.js";
|
|
42
43
|
import { runTaskChangeSetCommand } from "./commands/taskChangeSetCommands.js";
|
|
43
44
|
import { runTaskOverlapCommand } from "./commands/taskOverlapCommands.js";
|
|
@@ -46,9 +47,9 @@ import { runTaskWorkspaceCommand } from "./commands/taskWorkspaceCommands.js";
|
|
|
46
47
|
import { runWorkflowCommandAsync } from "./commands/workflowCommands.js";
|
|
47
48
|
import { createUpdatePorts } from "./cli/updatePorts.js";
|
|
48
49
|
import { createReleaseWorkflowPorts } from "./release/releaseWorkflowPorts.js";
|
|
49
|
-
import { readRuntimeIdentity } from "./release/runtimeRelease.js";
|
|
50
|
+
import { acquireHandoverLock, readRuntimeIdentity } from "./release/runtimeRelease.js";
|
|
50
51
|
import { renderReleaseActivateResult, renderReleaseInstallResult, renderReleaseList, runReleaseActivate, runReleaseInstall, runReleaseList } from "./commands/releaseCommands.js";
|
|
51
|
-
import { reconcileTaskRemoteBaselines } from "./commands/taskCompletionGate.js";
|
|
52
|
+
import { reconcileTaskRemoteBaselines, verifyTaskCompletionPublishedTree } from "./commands/taskCompletionGate.js";
|
|
52
53
|
import { runTaskBaseStatusCommand } from "./commands/taskBaseCommands.js";
|
|
53
54
|
import { assertTaskBaseFreshnessForCompletion, inspectTaskBaseFreshness } from "./repository/taskBaseFreshness.js";
|
|
54
55
|
import { FileCompletionManager, resolveCliIdentity } from "./completion/fileCompletionManager.js";
|
|
@@ -81,8 +82,10 @@ import { TmuxWebTerminalService } from "./web/tmuxWebTerminal.js";
|
|
|
81
82
|
import { listOperatorSessions, operatorSessionRef } from "./operator/operatorSessionHistory.js";
|
|
82
83
|
import { YUI_VERSION, yuiVersionIdentity } from "./version.js";
|
|
83
84
|
import { YUI_CONTROL_PLANE_DESCRIPTOR, YUI_TASK_RUNTIME_DESCRIPTOR, assertExactControlPlanePreflight, assertExactTaskRuntimeEnvironment, assertExactTaskRuntimeState, exactControlPlaneDigest, extractExactControlArgument, parseExactControlPlaneDescriptor } from "./runtime/exactControlPlane.js";
|
|
85
|
+
import { readSessionBootstrapManifest } from "./context/sessionBootstrapManifest.js";
|
|
84
86
|
import { builtinAgentDriverRegistry } from "./runtime/builtinAgentDrivers.js";
|
|
85
87
|
import { createTaskFinalReviewContract, extractTaskFinalReviewRequest } from "./review/taskFinalReviewContract.js";
|
|
88
|
+
import { prepareTaskFinalReviewContractRebindProof, resolveRecordedTaskFinalReviewContract } from "./review/taskFinalReviewContractRebind.js";
|
|
86
89
|
import { assessDeltaRecheck } from "./review/deltaRecheck.js";
|
|
87
90
|
import { deltaRecheckEnabled } from "./review/reviewConfig.js";
|
|
88
91
|
import { NodeGitWorkspace } from "./repository/gitWorkspace.js";
|
|
@@ -109,7 +112,7 @@ void main().catch((error) => {
|
|
|
109
112
|
process.exitCode = 5;
|
|
110
113
|
});
|
|
111
114
|
export async function main() {
|
|
112
|
-
const { contract: taskFinalReviewContract, verifiedStore } = await preflightManagedTaskControlPlane();
|
|
115
|
+
const { contract: taskFinalReviewContract, verifiedStore, controlPlane: exactCurrentControlPlane } = await preflightManagedTaskControlPlane();
|
|
113
116
|
if (args.length === 0) {
|
|
114
117
|
emit(renderCommandHelp((await import("./cli/commandCatalog.js")).ROOT_COMMAND, VERSION));
|
|
115
118
|
return;
|
|
@@ -944,6 +947,7 @@ export async function main() {
|
|
|
944
947
|
}
|
|
945
948
|
}
|
|
946
949
|
let completionSummary;
|
|
950
|
+
let completionPublishedTreeProof;
|
|
947
951
|
if (resolved[1] === "base" && resolved[2] === "status") {
|
|
948
952
|
const result = await runTaskBaseStatusCommand(resolved.slice(3), store);
|
|
949
953
|
emit(result.output, false, result.data);
|
|
@@ -958,12 +962,26 @@ export async function main() {
|
|
|
958
962
|
...(taskFinalReviewContract === undefined
|
|
959
963
|
? {}
|
|
960
964
|
: { taskFinalReviewContract })
|
|
961
|
-
});
|
|
965
|
+
}, completionRequest);
|
|
962
966
|
if (!completion.completed && !completion.activeTaskReview) {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
+
// An explicit refresh must fetch the remote object graph before the
|
|
968
|
+
// Publication proof resolves its exact commit. Without the flag the
|
|
969
|
+
// command remains offline and preserves the existing proof-first path.
|
|
970
|
+
const refreshedFreshness = refreshRemote
|
|
971
|
+
? await inspectTaskBaseFreshness(resolved[2], store, { refresh: true })
|
|
972
|
+
: undefined;
|
|
973
|
+
if (completionRequest.acceptedPublishedTreePublicationId !== undefined) {
|
|
974
|
+
completionPublishedTreeProof = await verifyTaskCompletionPublishedTree(completionRequest.taskId, completionRequest.acceptedPublishedTreePublicationId, store);
|
|
975
|
+
}
|
|
976
|
+
const freshness = refreshedFreshness
|
|
977
|
+
?? await inspectTaskBaseFreshness(resolved[2], store);
|
|
978
|
+
for (const warning of assertTaskBaseFreshnessForCompletion(freshness, {
|
|
979
|
+
...(completionPublishedTreeProof === undefined
|
|
980
|
+
? {}
|
|
981
|
+
: {
|
|
982
|
+
acceptedPublishedTreeProjectId: completionPublishedTreeProof.projectId
|
|
983
|
+
})
|
|
984
|
+
})) {
|
|
967
985
|
process.stderr.write(`Warning: ${warning}\n`);
|
|
968
986
|
}
|
|
969
987
|
// Keep completion offline by default. An explicit refresh is the only
|
|
@@ -973,6 +991,59 @@ export async function main() {
|
|
|
973
991
|
}
|
|
974
992
|
}
|
|
975
993
|
}
|
|
994
|
+
let taskFinalReviewRebindProof;
|
|
995
|
+
let taskFinalReviewRebindRequest;
|
|
996
|
+
let releaseTaskFinalReviewHandoverLock;
|
|
997
|
+
if (resolved[1] === "review" && resolved[2] === "rebind") {
|
|
998
|
+
if (!isCurrentGlobalOperator(store, process.env)) {
|
|
999
|
+
throw usageError("Task-final Review contract rebind requires the authenticated global Operator session.");
|
|
1000
|
+
}
|
|
1001
|
+
if (exactCurrentControlPlane === undefined) {
|
|
1002
|
+
throw usageError("Task-final Review contract rebind requires the exact current global Session CLI.");
|
|
1003
|
+
}
|
|
1004
|
+
taskFinalReviewRebindRequest = parseTaskFinalReviewContractRebindRequest(resolved.slice(3));
|
|
1005
|
+
}
|
|
1006
|
+
if ((resolved[1] === "review"
|
|
1007
|
+
&& ["request", "force-fresh", "retry", "rebind"].includes(resolved[2] ?? ""))
|
|
1008
|
+
|| resolved[1] === "complete") {
|
|
1009
|
+
const handoverLock = acquireHandoverLock(home);
|
|
1010
|
+
releaseTaskFinalReviewHandoverLock = handoverLock.release;
|
|
1011
|
+
}
|
|
1012
|
+
if (taskFinalReviewRebindRequest !== undefined) {
|
|
1013
|
+
const request = taskFinalReviewRebindRequest;
|
|
1014
|
+
try {
|
|
1015
|
+
taskFinalReviewRebindProof = prepareTaskFinalReviewContractRebindProof({
|
|
1016
|
+
home,
|
|
1017
|
+
taskId: request.taskId,
|
|
1018
|
+
fromControlPlaneDigest: request.fromControlPlaneDigest,
|
|
1019
|
+
toControlPlaneDigest: request.toControlPlaneDigest,
|
|
1020
|
+
fromReleaseId: request.fromReleaseId,
|
|
1021
|
+
toReleaseId: request.toReleaseId,
|
|
1022
|
+
currentControlPlane: exactCurrentControlPlane.descriptor
|
|
1023
|
+
});
|
|
1024
|
+
const workItems = store.listWorkItems(request.taskId);
|
|
1025
|
+
const reviewRounds = store.listReviewRounds(request.taskId);
|
|
1026
|
+
const resolution = resolveRecordedTaskFinalReviewContract(request.taskId, workItems, reviewRounds, store.listEvents(request.taskId));
|
|
1027
|
+
const activeRound = reviewRounds.find((round) => ((round.scope ?? "work-item") === "task"
|
|
1028
|
+
&& (round.status === "pending" || round.status === "running")));
|
|
1029
|
+
// An exact replay is a true no-op, even when the target Leader is live.
|
|
1030
|
+
// Invalid/stale source tuples also reach the command unchanged so its
|
|
1031
|
+
// transactional diagnosis cannot stop a healthy target runtime.
|
|
1032
|
+
if (resolution?.effective.controlPlaneDigest === request.fromControlPlaneDigest
|
|
1033
|
+
&& activeRound === undefined) {
|
|
1034
|
+
// The contract event and wake must never target a Provider
|
|
1035
|
+
// Conversation launched by the source release. Active Runs fail
|
|
1036
|
+
// closed; otherwise stop and retire that runtime under the handover
|
|
1037
|
+
// lock before the transactional event+wake commit.
|
|
1038
|
+
await workspaceCoordinator.cleanupTaskRoleRuntime(request.taskId, "leader");
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
catch (error) {
|
|
1042
|
+
releaseTaskFinalReviewHandoverLock();
|
|
1043
|
+
releaseTaskFinalReviewHandoverLock = undefined;
|
|
1044
|
+
throw error;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
976
1047
|
let candidateMaterialization;
|
|
977
1048
|
let candidateMaterializationCommitted = false;
|
|
978
1049
|
try {
|
|
@@ -987,7 +1058,7 @@ export async function main() {
|
|
|
987
1058
|
? await candidateSnapshotForTaskCommand(resolved, store, workspacePreparer, process.env, taskFinalReviewContract)
|
|
988
1059
|
: candidateMaterialization.snapshot;
|
|
989
1060
|
const directTaskMainSnapshot = await directTaskMainSnapshotForTaskCommand(resolved, store, workspacePreparer, process.env, taskFinalReviewContract);
|
|
990
|
-
const actualTaskReviewCandidate = await actualTaskReviewCandidateForTaskCommand(resolved, store, workspacePreparer, process.env
|
|
1061
|
+
const actualTaskReviewCandidate = await actualTaskReviewCandidateForTaskCommand(resolved, store, workspacePreparer, process.env);
|
|
991
1062
|
const deltaRecheckPreflight = await deltaRecheckPreflightForTaskCommand(resolved.slice(1), store, actualTaskReviewCandidate);
|
|
992
1063
|
const reviewWorkspaceResult = await reviewWorkspaceResultForTaskCommand(resolved, store, workspacePreparer, process.env);
|
|
993
1064
|
const executionLaneGitSnapshot = await executionLaneGitSnapshotForTaskCommand(resolved, store, workspacePreparer, process.env);
|
|
@@ -1001,7 +1072,13 @@ export async function main() {
|
|
|
1001
1072
|
...(taskFinalReviewContract === undefined
|
|
1002
1073
|
? {}
|
|
1003
1074
|
: { taskFinalReviewContract }),
|
|
1075
|
+
...(taskFinalReviewRebindProof === undefined
|
|
1076
|
+
? {}
|
|
1077
|
+
: { taskFinalReviewRebindProof }),
|
|
1004
1078
|
...(completionSummary === undefined ? {} : { completionSummary }),
|
|
1079
|
+
...(completionPublishedTreeProof === undefined
|
|
1080
|
+
? {}
|
|
1081
|
+
: { completionPublishedTreeProof }),
|
|
1005
1082
|
...(workItemIntegrationProof === undefined ? {} : { workItemIntegrationProof }),
|
|
1006
1083
|
...(candidateGitSnapshot === undefined ? {} : { candidateGitSnapshot }),
|
|
1007
1084
|
...(candidateMaterialization === undefined
|
|
@@ -1242,6 +1319,12 @@ export async function main() {
|
|
|
1242
1319
|
}
|
|
1243
1320
|
throw error;
|
|
1244
1321
|
}
|
|
1322
|
+
finally {
|
|
1323
|
+
if (releaseTaskFinalReviewHandoverLock !== undefined) {
|
|
1324
|
+
releaseTaskFinalReviewHandoverLock();
|
|
1325
|
+
releaseTaskFinalReviewHandoverLock = undefined;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1245
1328
|
}
|
|
1246
1329
|
if (resolved[0] === "jobs") {
|
|
1247
1330
|
emit(runJobCommand(resolved.slice(1), store, { runtime }));
|
|
@@ -1282,12 +1365,12 @@ async function preflightManagedTaskControlPlane() {
|
|
|
1282
1365
|
}
|
|
1283
1366
|
if (!exactRuntime) {
|
|
1284
1367
|
if (exactControlInvocation.digest !== undefined) {
|
|
1285
|
-
|
|
1368
|
+
return await preflightManagedGlobalControlPlane(exactControlInvocation.digest);
|
|
1286
1369
|
}
|
|
1287
1370
|
if (taskFinalReviewInvocation.request !== undefined) {
|
|
1288
1371
|
throw new Error("Task final-review contract requires a verified exact Task control-plane invocation.");
|
|
1289
1372
|
}
|
|
1290
|
-
return { contract: undefined, verifiedStore: undefined };
|
|
1373
|
+
return { contract: undefined, controlPlane: undefined, verifiedStore: undefined };
|
|
1291
1374
|
}
|
|
1292
1375
|
if (process.env.YUI_SESSION_SCOPE !== "task") {
|
|
1293
1376
|
throw new Error("Exact Task control-plane invocation requires a managed Task runtime.");
|
|
@@ -1331,8 +1414,13 @@ async function preflightManagedTaskControlPlane() {
|
|
|
1331
1414
|
}
|
|
1332
1415
|
: {});
|
|
1333
1416
|
const request = taskFinalReviewInvocation.request;
|
|
1334
|
-
if (request === undefined)
|
|
1335
|
-
return {
|
|
1417
|
+
if (request === undefined) {
|
|
1418
|
+
return {
|
|
1419
|
+
contract: undefined,
|
|
1420
|
+
controlPlane: { digest, descriptor: control },
|
|
1421
|
+
verifiedStore
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1336
1424
|
if (runtime.roleName !== "leader") {
|
|
1337
1425
|
throw new Error("Only the exact Task Leader invocation may establish a final-review contract.");
|
|
1338
1426
|
}
|
|
@@ -1345,9 +1433,50 @@ async function preflightManagedTaskControlPlane() {
|
|
|
1345
1433
|
reviewerRoleName: request.reviewerRoleName,
|
|
1346
1434
|
controlPlaneDigest: digest
|
|
1347
1435
|
}),
|
|
1436
|
+
controlPlane: { digest, descriptor: control },
|
|
1348
1437
|
verifiedStore
|
|
1349
1438
|
};
|
|
1350
1439
|
}
|
|
1440
|
+
async function preflightManagedGlobalControlPlane(digest) {
|
|
1441
|
+
if (process.env.YUI_SESSION_SCOPE !== "global") {
|
|
1442
|
+
throw new Error("Exact Task control-plane invocation requires its frozen runtime descriptors.");
|
|
1443
|
+
}
|
|
1444
|
+
if (taskFinalReviewInvocation.request !== undefined) {
|
|
1445
|
+
throw new Error("Task final-review contract establishment requires a verified exact Task control-plane invocation.");
|
|
1446
|
+
}
|
|
1447
|
+
const manifestPath = process.env.YUI_SESSION_MANIFEST;
|
|
1448
|
+
const sessionCliPath = process.env.YUI_SESSION_CLI;
|
|
1449
|
+
if (manifestPath === undefined || sessionCliPath === undefined) {
|
|
1450
|
+
throw new Error("Exact global control-plane invocation requires its Session Manifest and CLI.");
|
|
1451
|
+
}
|
|
1452
|
+
const manifest = readSessionBootstrapManifest(manifestPath);
|
|
1453
|
+
const expectedRoleKind = process.env.YUI_ROLE === "operator" ? "operator" : "global";
|
|
1454
|
+
if (manifest.owner.scope !== "global"
|
|
1455
|
+
|| manifest.roleKind !== expectedRoleKind
|
|
1456
|
+
|| resolve(manifest.controlPlane.sessionCliPath) !== resolve(sessionCliPath)
|
|
1457
|
+
|| manifest.controlPlane.digest !== digest) {
|
|
1458
|
+
throw new Error("Exact global control-plane invocation does not match its Session Manifest.");
|
|
1459
|
+
}
|
|
1460
|
+
const serializedDescriptor = readFileSync(manifest.controlPlane.descriptorPath, "utf8");
|
|
1461
|
+
const descriptor = parseExactControlPlaneDescriptor(serializedDescriptor);
|
|
1462
|
+
if (exactControlPlaneDigest(descriptor) !== digest
|
|
1463
|
+
|| resolve(manifest.controlPlane.descriptorPath) !== resolve(join(descriptor.yuiHome, "runtime", "control-plane", `${digest}.json`))
|
|
1464
|
+
|| resolve(manifestPath) !== resolve(join(descriptor.yuiHome, "runtime", "session-manifests", `${manifest.digest}.json`))) {
|
|
1465
|
+
throw new Error("Exact global Session Manifest does not match its control-plane descriptor.");
|
|
1466
|
+
}
|
|
1467
|
+
await assertExactControlPlanePreflight({
|
|
1468
|
+
serializedDescriptor,
|
|
1469
|
+
digest,
|
|
1470
|
+
actualExecutable: process.execPath,
|
|
1471
|
+
actualCliEntry: fileURLToPath(import.meta.url),
|
|
1472
|
+
actualHome: resolveYuiHome(process.env)
|
|
1473
|
+
});
|
|
1474
|
+
return {
|
|
1475
|
+
contract: undefined,
|
|
1476
|
+
controlPlane: { digest, descriptor },
|
|
1477
|
+
verifiedStore: openCompatibleFileTaskStore(descriptor.yuiHome)
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1351
1480
|
function cleanupCliError(error, fallbackResource) {
|
|
1352
1481
|
if (error instanceof WorkspaceCleanupBlockedError) {
|
|
1353
1482
|
return usageError(error.message, undefined, cleanupBlockedDetails(error.reason, error.resource, error.retryable));
|
|
@@ -1612,6 +1741,36 @@ async function prepareReviewLaneWorkspaces(taskId, reviewRoundId, store, prepare
|
|
|
1612
1741
|
return map;
|
|
1613
1742
|
}
|
|
1614
1743
|
async function directTaskMainSnapshotForTaskCommand(args, store, preparer, environment, taskFinalReviewContract) {
|
|
1744
|
+
const deliveryOption = args.indexOf("--delivery", 3);
|
|
1745
|
+
const deliveryPromotion = args[0] === "task"
|
|
1746
|
+
&& args[1] === "update"
|
|
1747
|
+
&& args[2] !== undefined
|
|
1748
|
+
&& (args.includes("--require-integration", 3)
|
|
1749
|
+
|| (deliveryOption >= 0 && args[deliveryOption + 1] === "integrated"));
|
|
1750
|
+
if (deliveryPromotion) {
|
|
1751
|
+
const task = store.getTask(args[2]);
|
|
1752
|
+
if (task === null
|
|
1753
|
+
|| (task.status !== "active" && task.status !== "draft")
|
|
1754
|
+
|| task.requireIntegration === true
|
|
1755
|
+
|| task.projectBindings.length === 0) {
|
|
1756
|
+
return undefined;
|
|
1757
|
+
}
|
|
1758
|
+
const workspace = store.getTaskWorkspace(task.id);
|
|
1759
|
+
if (task.status === "draft" && workspace === null)
|
|
1760
|
+
return undefined;
|
|
1761
|
+
if (workspace === null
|
|
1762
|
+
|| workspace.owner.type !== "task"
|
|
1763
|
+
|| workspace.owner.taskId !== task.id) {
|
|
1764
|
+
throw usageError(`Task has no authoritative main workspace: ${task.id}.`);
|
|
1765
|
+
}
|
|
1766
|
+
try {
|
|
1767
|
+
return await preparer.snapshotDirectTaskMain(workspace, task.projectBindings.map(({ projectId }) => projectId));
|
|
1768
|
+
}
|
|
1769
|
+
catch (error) {
|
|
1770
|
+
throw usageError(`Delivery promotion Task-main verification failed for ${task.id}: `
|
|
1771
|
+
+ `${error instanceof Error ? error.message : String(error)}`);
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1615
1774
|
if (taskFinalReviewContract === undefined
|
|
1616
1775
|
|| args[0] !== "task"
|
|
1617
1776
|
|| args[1] !== "work"
|
|
@@ -1642,7 +1801,7 @@ async function directTaskMainSnapshotForTaskCommand(args, store, preparer, envir
|
|
|
1642
1801
|
throw usageError(error instanceof Error ? error.message : String(error));
|
|
1643
1802
|
}
|
|
1644
1803
|
}
|
|
1645
|
-
async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, environment
|
|
1804
|
+
async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, environment) {
|
|
1646
1805
|
if (args[0] !== "task")
|
|
1647
1806
|
return undefined;
|
|
1648
1807
|
let taskId;
|
|
@@ -1651,12 +1810,9 @@ async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, en
|
|
|
1651
1810
|
if (task === null || task.status !== "active" || task.projectBindings.length === 0) {
|
|
1652
1811
|
return undefined;
|
|
1653
1812
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
&& !establishedFinalRound) {
|
|
1658
|
-
return undefined;
|
|
1659
|
-
}
|
|
1813
|
+
// Every Project-backed completion, including direct delivery, must freeze
|
|
1814
|
+
// a clean committed Task-main snapshot. Review policy only decides whether
|
|
1815
|
+
// that head also needs an independent ReviewRound.
|
|
1660
1816
|
taskId = task.id;
|
|
1661
1817
|
}
|
|
1662
1818
|
else if (args[1] === "review"
|
|
@@ -1673,6 +1829,15 @@ async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, en
|
|
|
1673
1829
|
taskId = reference.taskId;
|
|
1674
1830
|
}
|
|
1675
1831
|
}
|
|
1832
|
+
else if (args[1] === "review"
|
|
1833
|
+
&& args[2] === "force-fresh"
|
|
1834
|
+
&& args[3] !== undefined) {
|
|
1835
|
+
const reference = cliTaskRecordReference(args[3], "reviewRound", environment);
|
|
1836
|
+
const round = store.getReviewRound(reference.taskId, reference.localId);
|
|
1837
|
+
if (round !== null && (round.scope ?? "work-item") === "task") {
|
|
1838
|
+
taskId = reference.taskId;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1676
1841
|
else if (args[1] === "work"
|
|
1677
1842
|
&& args[2] === "review"
|
|
1678
1843
|
&& args[3] === "retry"
|
|
@@ -213,6 +213,36 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
|
|
|
213
213
|
else {
|
|
214
214
|
lines.push("", ...sectionError("workItems", report));
|
|
215
215
|
}
|
|
216
|
+
if (report.orchestration.status === "ok" && report.orchestration.data !== undefined) {
|
|
217
|
+
const orchestration = report.orchestration.data;
|
|
218
|
+
lines.push("", `Orchestration: ${orchestration.tasks.length} Task(s) · ${orchestration.advisoryCount} advisory finding(s)`);
|
|
219
|
+
if (orchestration.tasks.length > 0) {
|
|
220
|
+
lines.push(renderTable("Task orchestration metrics", [
|
|
221
|
+
{ header: "Task", minWidth: 7, maxWidth: 14 },
|
|
222
|
+
{ header: "Delivery", minWidth: 8, maxWidth: 10 },
|
|
223
|
+
{ header: "Runs", minWidth: 4, maxWidth: 6 },
|
|
224
|
+
{ header: "WIs", minWidth: 3, maxWidth: 5 },
|
|
225
|
+
{ header: "Review F/D/N", minWidth: 12, maxWidth: 16 },
|
|
226
|
+
{ header: "Integration A/F/R", minWidth: 17, maxWidth: 20 },
|
|
227
|
+
{ header: "Pre-progress gen", minWidth: 12, maxWidth: 16 },
|
|
228
|
+
{ header: "Terminal ws", minWidth: 10, maxWidth: 12 },
|
|
229
|
+
{ header: "Advice", minWidth: 6, maxWidth: 8 }
|
|
230
|
+
], orchestration.tasks.map((task) => [
|
|
231
|
+
task.taskId,
|
|
232
|
+
task.deliveryPath,
|
|
233
|
+
String(task.runs.total),
|
|
234
|
+
String(task.workItems),
|
|
235
|
+
`${task.reviews.full}/${task.reviews.delta}/${task.reviews.nonSemantic}`,
|
|
236
|
+
`${task.integrations.attempts}/${task.integrations.failed}/${task.integrations.repeatedIdentities}`,
|
|
237
|
+
String(task.providerGenerationsBeforeFirstProgress),
|
|
238
|
+
String(task.terminalWorkspaceCount),
|
|
239
|
+
String(task.advisories.length)
|
|
240
|
+
]), width));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
lines.push("", ...sectionError("orchestration", report));
|
|
245
|
+
}
|
|
216
246
|
if (report.storage.status === "ok" && report.storage.data !== undefined) {
|
|
217
247
|
const storage = report.storage.data;
|
|
218
248
|
lines.push("", `Storage: backend ${storage.backend} · state.json ${formatBytes(storage.stateJsonBytes)} · yui.db ${formatBytes(storage.databaseBytes)}`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { usageError } from "../errors/cliError.js";
|
|
2
2
|
import { createRoleSessionSet } from "../executor/agentExecutor.js";
|
|
3
|
-
import { listOperatorSessions, prepareOperatorNewSession, prepareOperatorResumeSession } from "../operator/operatorSessionHistory.js";
|
|
3
|
+
import { listOperatorSessions, projectOperatorStatus, prepareOperatorNewSession, prepareOperatorResumeSession } from "../operator/operatorSessionHistory.js";
|
|
4
4
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
5
5
|
import { formatRelativeTimestamp } from "../output/timePresentation.js";
|
|
6
6
|
import { updateGlobalRole } from "../role/role.js";
|
|
@@ -11,6 +11,7 @@ export function runOperatorCommand(args, store, options = {}) {
|
|
|
11
11
|
const [command, ...rest] = args;
|
|
12
12
|
switch (command) {
|
|
13
13
|
case "list": return listSessions(rest, store, options);
|
|
14
|
+
case "status": return status(rest, store, options);
|
|
14
15
|
case "new": return newSession(rest, store);
|
|
15
16
|
case "resume": return resumeSession(rest, store);
|
|
16
17
|
case "submit": return submit(rest, store, options);
|
|
@@ -20,6 +21,46 @@ export function runOperatorCommand(args, store, options = {}) {
|
|
|
20
21
|
: `Unknown command: operator ${command}`);
|
|
21
22
|
}
|
|
22
23
|
}
|
|
24
|
+
function status(args, store, options) {
|
|
25
|
+
if (args.length !== 0)
|
|
26
|
+
throw usageError("Operator status usage: yui operator status.");
|
|
27
|
+
const role = requireOperator(store);
|
|
28
|
+
const activeBinding = role.agentBindings[role.activeAgentId];
|
|
29
|
+
if (activeBinding === undefined) {
|
|
30
|
+
throw usageError(`Operator active Agent is not bound: ${role.activeAgentId}.`);
|
|
31
|
+
}
|
|
32
|
+
const projection = projectOperatorStatus(store.getGlobalRoleSessionSet(role.name), role.activeAgentId, activeBinding.adapterId);
|
|
33
|
+
const writer = projection.writer;
|
|
34
|
+
const writerLines = [
|
|
35
|
+
"Operator status",
|
|
36
|
+
"Active writer:",
|
|
37
|
+
` State: ${writer.state}`,
|
|
38
|
+
` Agent: ${writer.agentId}`,
|
|
39
|
+
` Adapter: ${adapterLabel(writer.adapterId)}`,
|
|
40
|
+
` Conversation: ${writer.sessionRef ?? "-"}`,
|
|
41
|
+
` Native session: ${writer.nativeSessionId ?? "-"}`,
|
|
42
|
+
` Session state: ${writer.sessionStatus ?? "-"}`
|
|
43
|
+
];
|
|
44
|
+
const history = projection.historicalConversations;
|
|
45
|
+
const historyOutput = history.length === 0
|
|
46
|
+
? "Historical conversations: none"
|
|
47
|
+
: renderTable("Historical conversations", [
|
|
48
|
+
{ header: "Updated", minWidth: 7, maxWidth: 12 },
|
|
49
|
+
{ header: "Agent", minWidth: 6, maxWidth: 16 },
|
|
50
|
+
{ header: "Conversation", minWidth: 20, maxWidth: 72 },
|
|
51
|
+
{ header: "State", minWidth: 7, maxWidth: 10 }
|
|
52
|
+
], history.map((session) => [
|
|
53
|
+
formatRelativeTimestamp(session.updatedAt, options.now?.() ?? new Date()),
|
|
54
|
+
adapterLabel(session.adapterId),
|
|
55
|
+
session.displayTitle,
|
|
56
|
+
session.state
|
|
57
|
+
]), options.width ?? defaultTableWidth());
|
|
58
|
+
return {
|
|
59
|
+
kind: "output",
|
|
60
|
+
output: `${writerLines.join("\n")}\n\n${historyOutput}\n`,
|
|
61
|
+
data: projection
|
|
62
|
+
};
|
|
63
|
+
}
|
|
23
64
|
function submit(rest, store, options) {
|
|
24
65
|
const usage = "Operator submit usage: yui operator submit (<body>|--body-file <path|->) [--task <id>].";
|
|
25
66
|
const positionals = [];
|