@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.
Files changed (68) hide show
  1. package/ARCHITECTURE.md +40 -22
  2. package/README.md +61 -9
  3. package/dist/cli/commandCatalog.js +31 -14
  4. package/dist/cli/operatorWizard.js +10 -20
  5. package/dist/cli.js +187 -22
  6. package/dist/commands/executionAuditCommands.js +30 -0
  7. package/dist/commands/operatorCommands.js +42 -1
  8. package/dist/commands/taskCommands.js +648 -74
  9. package/dist/commands/taskCompletionGate.js +166 -2
  10. package/dist/commands/taskContextCommand.js +6 -1
  11. package/dist/commands/taskInputCommands.js +48 -10
  12. package/dist/commands/taskNextActionCommand.js +36 -3
  13. package/dist/context/runContextPack.js +19 -4
  14. package/dist/context/sessionBootstrapManifest.js +83 -2
  15. package/dist/controller/clientRuntime.js +7 -7
  16. package/dist/controller/controller.js +16 -8
  17. package/dist/controller/fileSchedulerStoreAdapter.js +64 -5
  18. package/dist/controller/handoverCandidate.js +10 -3
  19. package/dist/controller/sessionNotify.js +4 -22
  20. package/dist/executor/agentAdapter.js +2 -2
  21. package/dist/executor/agentExecutor.js +25 -5
  22. package/dist/executor/fileRoleLaunchPlanner.js +16 -11
  23. package/dist/integration/gitIntegrationService.js +50 -2
  24. package/dist/integration/integrationCheckEvidenceReuse.js +53 -0
  25. package/dist/observability/executionAudit.js +47 -1
  26. package/dist/observability/faultClassification.js +6 -4
  27. package/dist/observability/orchestrationMetrics.js +196 -0
  28. package/dist/operator/operatorSessionHistory.js +36 -0
  29. package/dist/release/releaseHandover.js +7 -5
  30. package/dist/release/runtimeRelease.js +15 -0
  31. package/dist/repository/gitWorkspace.js +7 -4
  32. package/dist/repository/taskBaseFreshness.js +4 -2
  33. package/dist/repository/taskWorkspaceCoordinator.js +13 -10
  34. package/dist/review/deltaRecheck.js +3 -2
  35. package/dist/review/reviewFindingLedger.js +5 -4
  36. package/dist/review/reviewOutcomeClassifier.js +252 -54
  37. package/dist/review/taskFinalReviewContractEvent.js +1 -0
  38. package/dist/review/taskFinalReviewContractRebind.js +350 -0
  39. package/dist/run/agentRun.js +2 -2
  40. package/dist/run/runIdentity.js +10 -70
  41. package/dist/runtime/agentHost.js +3 -4
  42. package/dist/runtime/codexAppServerRuntime.js +6 -0
  43. package/dist/runtime/firstProgressStopLoss.js +52 -0
  44. package/dist/runtime/launchBroker.js +10 -2
  45. package/dist/runtime/runtimeDeadlines.js +14 -0
  46. package/dist/runtime/sessionTitle.js +24 -12
  47. package/dist/runtime/structuredProviderHost.js +7 -1
  48. package/dist/runtime/tmuxAdapters.js +10 -3
  49. package/dist/scheduler/activeRoleRunDelivery.js +20 -18
  50. package/dist/scheduler/leaderWakeupProcessor.js +33 -2
  51. package/dist/scheduler/wakeReason.js +2 -0
  52. package/dist/storage/sqliteStore.js +10 -1
  53. package/dist/storage/taskStore.js +12 -1
  54. package/dist/task/completionReadiness.js +91 -19
  55. package/dist/task/deliveryGuard.js +3 -1
  56. package/dist/task/nextAction.js +146 -51
  57. package/dist/task/publicationReference.js +1 -0
  58. package/dist/task/repairWave.js +14 -1
  59. package/dist/task/task.js +10 -0
  60. package/dist/web/webSnapshot.js +7 -1
  61. package/dist/workItem/workItem.js +12 -0
  62. package/dist/workspace/workItemChangeSetManager.js +2 -1
  63. package/i18n/README.zh-CN.md +28 -8
  64. package/package.json +1 -1
  65. package/skills/yui-leader/SKILL.md +79 -32
  66. package/skills/yui-operator/SKILL.md +51 -10
  67. package/skills/yui-reviewer/SKILL.md +23 -0
  68. 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
- const freshness = await inspectTaskBaseFreshness(resolved[2], store, {
964
- refresh: refreshRemote
965
- });
966
- for (const warning of assertTaskBaseFreshnessForCompletion(freshness)) {
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, taskFinalReviewContract);
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
- throw new Error("Exact Task control-plane invocation requires its frozen runtime descriptors.");
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 { contract: undefined, verifiedStore };
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, taskFinalReviewContract) {
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
- const establishedFinalRound = store.listReviewRounds(task.id).some((round) => ((round.scope ?? "work-item") === "task"));
1655
- if (taskFinalReviewContract === undefined
1656
- && store.getReviewConfig()?.trigger !== "final"
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 = [];