@zq-silk/yui 0.16.1 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/ARCHITECTURE.md +12 -0
  2. package/ARCHITECTURE.zh-CN.md +8 -0
  3. package/README.md +3 -0
  4. package/dist/agent/managedRuntimeEnvironment.js +0 -4
  5. package/dist/agentRun/agentRun.js +7 -17
  6. package/dist/cli/agentConfigurationPicker.js +24 -21
  7. package/dist/cli/commandCatalog.js +18 -10
  8. package/dist/cli/roleWizard.js +41 -30
  9. package/dist/cli/updateCommand.js +35 -13
  10. package/dist/cli/updateOrchestrator.js +73 -33
  11. package/dist/cli/updatePorts.js +40 -17
  12. package/dist/cli.js +35 -26
  13. package/dist/commands/controllerCommands.js +1 -1
  14. package/dist/commands/executionAuditCommands.js +2 -2
  15. package/dist/commands/projectCommands.js +1 -1
  16. package/dist/commands/releaseCommands.js +9 -38
  17. package/dist/commands/taskCommands.js +84 -81
  18. package/dist/commands/taskCompletionGate.js +0 -117
  19. package/dist/commands/taskRoleRuntimeStatus.js +1 -1
  20. package/dist/commands/taskUpstreamCommands.js +93 -54
  21. package/dist/context/runContextPack.js +30 -54
  22. package/dist/context/runInputContract.js +9 -0
  23. package/dist/context/sessionBootstrapManifest.js +11 -19
  24. package/dist/controller/agentHostObservation.js +4 -2
  25. package/dist/controller/controller.js +8 -6
  26. package/dist/controller/fileSchedulerStoreAdapter.js +85 -18
  27. package/dist/controller/globalInputDelivery.js +28 -7
  28. package/dist/controller/globalRuntimeAttention.js +34 -0
  29. package/dist/controller/operatorNotification.js +31 -0
  30. package/dist/controller/providerRetryAdmission.js +3 -1
  31. package/dist/controller/providerRetryDelivery.js +10 -3
  32. package/dist/controller/runtime.js +1 -27
  33. package/dist/controller/sessionOwnerReconciliation.js +42 -24
  34. package/dist/controller/structuredProviderObservation.js +27 -0
  35. package/dist/controller/updateReconciliation.js +72 -20
  36. package/dist/doctor/doctor.js +2 -1
  37. package/dist/executor/agentAdapter.js +28 -96
  38. package/dist/executor/agentConfigurationCatalog.js +13 -68
  39. package/dist/executor/agentConfigurationFields.js +120 -0
  40. package/dist/executor/agentConfigurationProbe.js +55 -80
  41. package/dist/executor/agentExecutor.js +5 -2
  42. package/dist/executor/executorRegistry.js +0 -9
  43. package/dist/executor/fileRoleLaunchPlanner.js +12 -11
  44. package/dist/interaction/operatorPresentation.js +2 -1
  45. package/dist/message/messageContinuation.js +8 -9
  46. package/dist/observability/executionAudit.js +1 -10
  47. package/dist/observability/runtimeIdentity.js +0 -23
  48. package/dist/output/agentConfigurationPresentation.js +4 -2
  49. package/dist/release/releaseHandover.js +2 -2
  50. package/dist/release/releaseIdempotencyStore.js +0 -23
  51. package/dist/release/releaseWorkflowPorts.js +8 -4
  52. package/dist/repository/gitWorkspace.js +66 -19
  53. package/dist/repository/taskWorkspacePreparer.js +75 -68
  54. package/dist/resources/resourceRegistry.js +90 -44
  55. package/dist/resources/sqliteResourceRegistry.js +3 -5
  56. package/dist/runtime/acpSession.js +21 -5
  57. package/dist/runtime/agentEndpoint.js +4 -1
  58. package/dist/runtime/agentHost.js +22 -62
  59. package/dist/runtime/agentHostCleanup.js +85 -0
  60. package/dist/runtime/agentHostProtocol.js +1 -1
  61. package/dist/runtime/builtinAgentDrivers.js +46 -119
  62. package/dist/runtime/builtinTranscriptObserver.js +10 -6
  63. package/dist/runtime/codexAppServerRuntime.js +55 -89
  64. package/dist/runtime/jsonLineChannel.js +35 -7
  65. package/dist/runtime/providerContinuationReconciliationService.js +42 -3
  66. package/dist/runtime/providerRetry.js +15 -0
  67. package/dist/runtime/providerRuntimeReconciler.js +12 -2
  68. package/dist/runtime/structuredProviderHost.js +106 -81
  69. package/dist/scheduler/activeRoleRunDelivery.js +5 -1
  70. package/dist/scheduler/operatorInputNotificationProcessor.js +7 -17
  71. package/dist/storage/upgrade/upgradeOrchestrator.js +0 -10
  72. package/dist/task/nextAction.js +33 -23
  73. package/dist/task/task.js +2 -1
  74. package/dist/web/assets/assetManifest.js +2 -0
  75. package/dist/web/assets/client/app.js +72 -3
  76. package/dist/web/assets/client/components.js +2 -1
  77. package/dist/web/assets/client/i18n.js +2 -0
  78. package/dist/web/assets/client/taskSummary.js +345 -0
  79. package/dist/web/assets/client/taskSurface.js +44 -26
  80. package/dist/web/assets/client/view.js +33 -0
  81. package/dist/web/assets/shell.js +1 -0
  82. package/dist/web/assets/styles/cards.js +21 -0
  83. package/dist/web/webServer.js +39 -5
  84. package/dist/web/webSessions.js +165 -0
  85. package/dist/web/webSnapshot.js +23 -0
  86. package/dist/web/webTaskSurface.js +23 -0
  87. package/docs/managed-turn-and-session-runtime.md +31 -0
  88. package/docs/managed-turn-and-session-runtime.zh-CN.md +23 -0
  89. package/docs/observability/README.md +47 -0
  90. package/docs/observability/README.zh-CN.md +37 -0
  91. package/docs/project-refresh.md +9 -0
  92. package/docs/project-refresh.zh-CN.md +8 -0
  93. package/docs/provider-retry.md +35 -0
  94. package/docs/release-workflow.md +124 -20
  95. package/docs/release-workflow.zh-CN.md +103 -14
  96. package/docs/roles-and-configuration.md +30 -0
  97. package/docs/roles-and-configuration.zh-CN.md +20 -0
  98. package/docs/task-delivery.md +109 -0
  99. package/docs/task-delivery.zh-CN.md +80 -0
  100. package/docs/task-discovery.md +9 -0
  101. package/docs/task-discovery.zh-CN.md +6 -0
  102. package/docs/testing/verification-levels.md +29 -11
  103. package/docs/testing/verification-levels.zh-CN.md +25 -7
  104. package/i18n/README.zh-CN.md +2 -0
  105. package/package.json +1 -1
  106. package/skills/yui-leader/SKILL.md +11 -0
  107. package/skills/yui-leader/references/execution.md +22 -0
  108. package/skills/yui-leader/references/planning.md +6 -2
  109. package/skills/yui-operator/SKILL.md +45 -13
  110. package/skills/yui-operator/references/task-delivery.md +99 -0
  111. package/skills/yui-runtime/SKILL.md +5 -3
  112. package/skills/yui-runtime/references/publication.md +56 -5
  113. package/skills/yui-runtime/references/recovery.md +12 -2
  114. package/dist/runtime/agentHostCompatibility.js +0 -127
@@ -1,10 +1,10 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { isDeepStrictEqual } from "node:util";
3
3
  import { agentExecutionComponentLabel } from "../agent/executionComponents.js";
4
- import { createRun, runExecutionObservation, runPurposeAdmitsTaskState, withRunContextSnapshot } from "../agentRun/agentRun.js";
4
+ import { createRun, runExecutionObservation, runPurposeAdmitsTaskState } from "../agentRun/agentRun.js";
5
5
  import { isGitArtifactRefString, parseGitArtifactRef } from "../artifacts/gitArtifactRef.js";
6
6
  import { contextSnapshotRef } from "../context/contextSnapshot.js";
7
- import { buildRunContextDelta, buildRunContextPack, contextSnapshotDeltaRefIds, expandRunContextRef, freezeReviewStageContextSnapshot, freezeRunContextSnapshot, freezeWorkItemExecutionAssignmentContextSnapshot, synthesisSourceRunIds } from "../context/runContextPack.js";
7
+ import { buildRunContextDelta, buildRunContextPack, contextSnapshotDeltaRefIds, expandRunContextRef, freezeReviewStageContextSnapshot, freezeRunContextSnapshot, freezeWorkItemExecutionAssignmentContextSnapshot, readRunContextSnapshot, synthesisSourceRunIds } from "../context/runContextPack.js";
8
8
  import { createRunInput } from "../context/runInputContract.js";
9
9
  import { parseTaskCatalogOptions, readTaskCatalog, renderTaskCatalog } from "../context/taskCatalog.js";
10
10
  import { listContextMessages } from "../context/taskContext.js";
@@ -16,7 +16,7 @@ import { dispatchReviewSynthesis, selectedReviewSynthesisProducers } from "../ex
16
16
  import { createExecutionGroup, createReviewExecutionAssignment, createWorkItemExecutionAssignment, createWorkItemExecutionGroup, updateExecutionLane as updateUnifiedExecutionLane, updateWorkItemExecutionLane, workItemExecutionGroupSettled } from "../execution/workItemExecution.js";
17
17
  import { projectWorkItemExecution } from "../execution/workItemExecutionProjection.js";
18
18
  import { dispatchWorkItemSynthesis, selectedWorkItemSynthesisProducers } from "../execution/workItemMainRun.js";
19
- import { createRoleSessionSet, roleAgentSessionResumeMode, taskRoleControlTarget, updateTaskRoleProviderRuntime } from "../executor/agentExecutor.js";
19
+ import { createRoleSessionSet, roleAgentSessionResumeMode, roleSessionControlTarget, updateTaskRoleProviderRuntime } from "../executor/agentExecutor.js";
20
20
  import { resolveEffectiveLaunch } from "../executor/effectiveLaunch.js";
21
21
  import { cancelInputRequest } from "../input/inputRequest.js";
22
22
  import { retireExactActiveRun, terminalizeExactTaskRun, validateExactRunReviewRound } from "../lifecycle/exactRunTerminalization.js";
@@ -233,16 +233,17 @@ export function parseTaskCompletionRequest(args, summaryOverride) {
233
233
  taskId: parsed.positionals[0],
234
234
  summary,
235
235
  artifactRefs: parsed.multiOptions.get("--artifact-ref") ?? [],
236
+ refreshRemote: parsed.options.has("--refresh-remote"),
236
237
  ...(acceptedPublishedTreePublicationId === undefined
237
238
  ? {}
238
239
  : { acceptedPublishedTreePublicationId })
239
240
  };
240
241
  }
241
242
  /**
242
- * Check every read-only completion blocker before a caller resolves remote
243
- * baselines or creates an Integration Attempt. The transactional completion
243
+ * Check every read-only completion blocker before a caller observes remote
244
+ * baselines. The transactional completion
244
245
  * path invokes this same preflight and then repeats its checks while holding
245
- * the store write fence, so remote reconciliation can never get ahead of the
246
+ * the store write fence, so remote observation can never get ahead of the
246
247
  * local lifecycle/readiness gate.
247
248
  *
248
249
  * Issue 06: the blocker enumeration is the pure `projectCompletionReadiness`
@@ -262,7 +263,7 @@ export function preflightTaskCompletion(taskId, store, options = {}, _request =
262
263
  if (task.status !== "active")
263
264
  throw usageError(`Task is not active: ${task.id}.`);
264
265
  // Resolve the durable Task-local Reviewer policy before any remote fetch or
265
- // Integration write. Historical control-plane identity is audit evidence,
266
+ // final Review preparation. Historical control-plane identity is audit evidence,
266
267
  // not a capability that every compatible CLI must reproduce.
267
268
  const taskFinalReviewContract = taskFinalReviewContractForMutation(store, task.id, options);
268
269
  const activeTaskReview = store.listReviewRounds(task.id).some((round) => (round.scope === "task"
@@ -274,7 +275,7 @@ export function preflightTaskCompletion(taskId, store, options = {}, _request =
274
275
  const readiness = projectCompletionReadiness(readinessFacts);
275
276
  // An active Task-final Review is not a preflight failure: the transactional
276
277
  // path resumes a pending Round (or reports the running one) via
277
- // `prepareFinalTaskReview`, and the CLI skips remote reconciliation while
278
+ // `prepareFinalTaskReview`, and the CLI skips remote observation while
278
279
  // `activeTaskReview` is true. The blocker stays in the shared projection
279
280
  // so other surfaces (next-action, future readers) see the full rule set.
280
281
  const blockers = readiness.blockers.filter((blocker) => blocker.code !== "active-task-review");
@@ -1055,6 +1056,7 @@ function completeTaskCommand(args, store, options) {
1055
1056
  return {
1056
1057
  task,
1057
1058
  changed: false,
1059
+ projectHeads: undefined,
1058
1060
  completionAdvisories: [],
1059
1061
  finalReview: undefined
1060
1062
  };
@@ -1076,6 +1078,7 @@ function completeTaskCommand(args, store, options) {
1076
1078
  return {
1077
1079
  task,
1078
1080
  changed: false,
1081
+ projectHeads: actualTaskCandidate?.projects ?? [],
1079
1082
  completionAdvisories: [],
1080
1083
  finalReview,
1081
1084
  };
@@ -1167,6 +1170,7 @@ function completeTaskCommand(args, store, options) {
1167
1170
  return {
1168
1171
  task: completed,
1169
1172
  changed: true,
1173
+ projectHeads: actualTaskCandidate?.projects ?? [],
1170
1174
  completionAdvisories: readiness.advisories,
1171
1175
  finalReview: undefined
1172
1176
  };
@@ -1174,13 +1178,21 @@ function completeTaskCommand(args, store, options) {
1174
1178
  if (result.changed) {
1175
1179
  notifyMailbox(options.runtime, { kind: "operator" });
1176
1180
  }
1181
+ const headOutput = (result.projectHeads ?? []).map(({ projectId, commit }) => (`Task HEAD ${projectId}: ${commit}\n`)).join("");
1177
1182
  if (result.finalReview !== undefined) {
1178
- const status = result.finalReview.status === "pending"
1179
- ? `Final Task Review requested as ${result.finalReview.id}.`
1180
- : `Final Task Review is blocked: ${result.finalReview.failure?.message ?? result.finalReview.id}.`;
1181
- return output(`${status}\n`, {
1183
+ const round = result.finalReview;
1184
+ const stage = round.status === "pending" ? "review-pending"
1185
+ : round.status === "running" ? "review-running" : "review-blocked";
1186
+ const status = round.status === "pending"
1187
+ ? `Final Task Review requested as ${round.id}.`
1188
+ : round.status === "running"
1189
+ ? `Final Task Review is still running: ${round.id}.`
1190
+ : `Final Task Review ${round.id} is blocked: ${round.failure?.message ?? round.status}.`;
1191
+ return output(`${status}\nTask ${result.task.id} remains active.\n${headOutput}`, {
1192
+ stage,
1182
1193
  task: result.task,
1183
- reviewRound: result.finalReview
1194
+ projectHeads: result.projectHeads,
1195
+ reviewRound: round
1184
1196
  });
1185
1197
  }
1186
1198
  const completionOutput = result.changed
@@ -1190,8 +1202,10 @@ function completeTaskCommand(args, store, options) {
1190
1202
  ? ""
1191
1203
  : `Cleanup advisories (non-blocking; settle before archive):\n`
1192
1204
  + result.completionAdvisories.map((advisory) => (`- ${advisory.code} (${advisory.ref.kind} ${advisory.ref.id}): ${advisory.fix}`)).join("\n").concat("\n");
1193
- return output(completionOutput + advisoryOutput, {
1205
+ return output(completionOutput + headOutput + advisoryOutput, {
1206
+ stage: result.changed ? "completed" : "already-completed",
1194
1207
  task: result.task,
1208
+ ...(result.projectHeads === undefined ? {} : { projectHeads: result.projectHeads }),
1195
1209
  completionAdvisories: result.completionAdvisories
1196
1210
  });
1197
1211
  }
@@ -2534,7 +2548,7 @@ function taskRoleSessionCommand(args, store, options) {
2534
2548
  throw usageError("Use task role session new to request your own replacement and end this turn; synchronous self-stop cannot return.", usage);
2535
2549
  }
2536
2550
  const sessions = tx.getTaskRoleSessionSet(task.id, role.name);
2537
- const session = taskRoleControlTarget(sessions);
2551
+ const session = roleSessionControlTarget(sessions);
2538
2552
  if (session === undefined || session.adapterId === undefined) {
2539
2553
  throw usageError(`Task Role has no active Session: ${task.id}/${role.name}.`, usage);
2540
2554
  }
@@ -3494,38 +3508,36 @@ function dispatchWork(args, store, options) {
3494
3508
  workspace,
3495
3509
  workItemWriteProjectIds: item.writeProjectIds
3496
3510
  });
3511
+ tx.saveWorkItem(task.id, workItemForDispatch);
3497
3512
  const runId = tx.nextRunId(task.id);
3513
+ const snapshot = freezeRunContextSnapshot(tx, {
3514
+ taskId: task.id,
3515
+ roleName: role.name,
3516
+ purpose: "execution",
3517
+ workItemId: item.id,
3518
+ workspace
3519
+ }, now, "controller");
3498
3520
  const run = createRun(runId, task.id, role.name, roleAgentSessionResumeMode(tx.getTaskRoleSessionSet(task.id, role.name), effective.agentId, effective), createRunInput({
3499
3521
  source: { type: "yui", channel: "workitem-dispatch" },
3500
3522
  directive: rawInput,
3501
- deltaRefIds: []
3523
+ contextSnapshotRef: contextSnapshotRef(snapshot),
3524
+ deltaRefIds: contextSnapshotDeltaRefIds(tx, snapshot)
3502
3525
  }), now, {
3503
3526
  workItemId: item.id,
3504
3527
  workspace,
3505
3528
  effective
3506
3529
  });
3507
- const snapshot = freezeRunContextSnapshot(tx, {
3508
- taskId: task.id,
3509
- roleName: run.roleName,
3510
- purpose: "execution",
3511
- workItemId: item.id
3512
- }, now, "controller");
3513
- const withContext = withRunContextSnapshot(run, contextSnapshotRef(snapshot), contextSnapshotDeltaRefIds(tx, snapshot));
3514
- if (workItemForDispatch.status !== "open") {
3515
- workItemForDispatch = updateWorkItemStatus(workItemForDispatch, "open", now);
3516
- }
3517
- tx.saveWorkItem(task.id, workItemForDispatch);
3518
- tx.saveRun(withContext);
3519
- tx.saveActiveRun(withContext);
3530
+ tx.saveRun(run);
3531
+ tx.saveActiveRun(run);
3520
3532
  enqueueRoleRunDispatch(tx, {
3521
3533
  taskId: task.id,
3522
3534
  roleName: role.name,
3523
- runId: withContext.id,
3535
+ runId: run.id,
3524
3536
  reason: "turn-dispatched",
3525
3537
  occurredAt: now
3526
3538
  });
3527
- recordTaskEvent(tx, task.id, "run.dispatched", runLaunchEventPayload(withContext), now);
3528
- return { kind: "direct", runs: [withContext] };
3539
+ recordTaskEvent(tx, task.id, "run.dispatched", runLaunchEventPayload(run), now);
3540
+ return { kind: "direct", runs: [run] };
3529
3541
  }
3530
3542
  const groupId = `execution-group-${tx.peekNextRunId(task.id)}`;
3531
3543
  if (workItemForDispatch !== item) {
@@ -3597,10 +3609,18 @@ function dispatchWork(args, store, options) {
3597
3609
  }
3598
3610
  tx.saveWorkItem(task.id, workItemForDispatch);
3599
3611
  const runs = plans.map((plan, index) => {
3612
+ const snapshot = freezeRunContextSnapshot(tx, {
3613
+ taskId: task.id,
3614
+ roleName: plan.role.name,
3615
+ purpose: "execution",
3616
+ workItemId: item.id,
3617
+ workspace: plan.managedWorkspace
3618
+ }, now, "controller", assignment.contextSnapshotRef);
3600
3619
  const run = createRun(plan.runId, task.id, plan.role.name, plan.dispatchMode, createRunInput({
3601
3620
  source: { type: "yui", channel: "workitem-dispatch" },
3602
3621
  directive: assignment.input,
3603
- deltaRefIds: []
3622
+ contextSnapshotRef: contextSnapshotRef(snapshot),
3623
+ deltaRefIds: contextSnapshotDeltaRefIds(tx, snapshot)
3604
3624
  }), now, {
3605
3625
  workItemId: item.id,
3606
3626
  executionGroupId: group.id,
@@ -3608,28 +3628,21 @@ function dispatchWork(args, store, options) {
3608
3628
  workspace: plan.managedWorkspace,
3609
3629
  effective: plan.effective
3610
3630
  });
3611
- const snapshot = freezeRunContextSnapshot(tx, {
3612
- taskId: task.id,
3613
- roleName: run.roleName,
3614
- purpose: "execution",
3615
- workItemId: item.id
3616
- }, now, "controller", assignment.contextSnapshotRef);
3617
- const withContext = withRunContextSnapshot(run, contextSnapshotRef(snapshot), contextSnapshotDeltaRefIds(tx, snapshot));
3618
3631
  const prepared = options.executionLaneWorkspaces?.get(group.lanes[index].id);
3619
3632
  if (prepared !== undefined && tx.getManagedWorkspace(prepared.owner) === null) {
3620
3633
  tx.saveManagedWorkspace(prepared);
3621
3634
  }
3622
- tx.saveRun(withContext);
3623
- tx.saveActiveRun(withContext);
3635
+ tx.saveRun(run);
3636
+ tx.saveActiveRun(run);
3624
3637
  enqueueRoleRunDispatch(tx, {
3625
3638
  taskId: task.id,
3626
3639
  roleName: plan.role.name,
3627
- runId: withContext.id,
3640
+ runId: run.id,
3628
3641
  reason: "turn-dispatched",
3629
3642
  occurredAt: now
3630
3643
  });
3631
- recordTaskEvent(tx, task.id, "run.dispatched", runLaunchEventPayload(withContext), now);
3632
- return withContext;
3644
+ recordTaskEvent(tx, task.id, "run.dispatched", runLaunchEventPayload(run), now);
3645
+ return run;
3633
3646
  });
3634
3647
  return { kind: "replicated", runs };
3635
3648
  });
@@ -4590,7 +4603,6 @@ function retireRun(args, store, options) {
4590
4603
  const parsed = parseTail(args, new Set([
4591
4604
  "--reason",
4592
4605
  "--expected-progress-at",
4593
- "--progress-at",
4594
4606
  "--agent-id",
4595
4607
  "--adapter-id",
4596
4608
  "--native-session-id"
@@ -4611,12 +4623,7 @@ function retireRun(args, store, options) {
4611
4623
  return { task, run: run, changed: false };
4612
4624
  }
4613
4625
  if (run.status === "active") {
4614
- const expectedProgressAt = requiredOption(parsed.options, parsed.options.has("--expected-progress-at")
4615
- ? "--expected-progress-at"
4616
- : "--progress-at");
4617
- if (parsed.options.has("--expected-progress-at") && parsed.options.has("--progress-at")) {
4618
- throw usageError("--expected-progress-at and --progress-at are mutually exclusive.", usage);
4619
- }
4626
+ const expectedProgressAt = requiredOption(parsed.options, "--expected-progress-at");
4620
4627
  const agentId = requiredOption(parsed.options, "--agent-id");
4621
4628
  const adapterId = requiredOption(parsed.options, "--adapter-id");
4622
4629
  const nativeSessionId = parsed.options.get("--native-session-id");
@@ -4646,11 +4653,9 @@ function retireRun(args, store, options) {
4646
4653
  runId: run.id,
4647
4654
  reason,
4648
4655
  ...(parsed.options.get("--expected-progress-at") === undefined
4649
- && parsed.options.get("--progress-at") === undefined
4650
4656
  ? {}
4651
4657
  : {
4652
4658
  expectedProgressAt: parsed.options.get("--expected-progress-at")
4653
- ?? parsed.options.get("--progress-at")
4654
4659
  }),
4655
4660
  ...(parsed.options.get("--native-session-id") === undefined
4656
4661
  ? {}
@@ -4679,16 +4684,17 @@ function retireRun(args, store, options) {
4679
4684
  function runContextCommand(args, store, options) {
4680
4685
  const [first, ...rest] = args;
4681
4686
  if (first === "expand") {
4682
- const usage = "Task run context expand usage: yui task run context expand <task>/<run> <ref-id> [--store <store>] [--mode full].";
4687
+ const usage = "Task run context expand usage: yui task run context expand <task>/<run> <ref-id> --store <store> [--mode full].";
4683
4688
  const parsed = parseTail(rest, new Set(["--store", "--mode"]), usage);
4684
4689
  exactPositionals(parsed.positionals, 2, usage);
4690
+ const refStore = requiredOption(parsed.options, "--store");
4685
4691
  const mode = parsed.options.get("--mode");
4686
4692
  if (mode !== undefined && mode !== "full") {
4687
4693
  throw usageError("AgentRun Context expansion mode must be full.", usage);
4688
4694
  }
4689
4695
  const { taskId, runId } = parseRunContextReference(parsed.positionals[0]);
4690
4696
  authorizeRunContext(store, taskId, runId, options.environment);
4691
- const expanded = store.transaction((tx) => expandRunContextRef(tx, taskId, runId, parsed.positionals[1], optionalNonEmptyOption(parsed.options, "--store")));
4697
+ const expanded = store.transaction((tx) => expandRunContextRef(tx, taskId, runId, parsed.positionals[1], refStore));
4692
4698
  return output(`${JSON.stringify(expanded, null, 2)}\n`, { context: expanded });
4693
4699
  }
4694
4700
  if (first === "delta") {
@@ -4908,7 +4914,11 @@ function retryRun(args, store, options) {
4908
4914
  function retryRunOperation(args, store, options) {
4909
4915
  exactPositionals(args, 1, "Task run retry usage: yui task run retry <task>/<run>.");
4910
4916
  const now = clock(options);
4911
- const previous = store.transaction((tx) => requireRun(tx, args[0], options));
4917
+ const previous = store.transaction((tx) => {
4918
+ const run = requireRun(tx, args[0], options);
4919
+ readRunContextSnapshot(tx, run);
4920
+ return run;
4921
+ });
4912
4922
  if (previous.purpose === "review") {
4913
4923
  return retryFailedReviewRun(previous, store, options, now);
4914
4924
  }
@@ -5008,13 +5018,6 @@ function retryRunOperation(args, store, options) {
5008
5018
  }
5009
5019
  if (retryItem !== null)
5010
5020
  assertWorkItemDependenciesCompletedForCommand(tx, retryItem);
5011
- const runWorkspace = previous.workspace
5012
- ?? (retryItem === null
5013
- ? tx.getTaskWorkspace(task.id)
5014
- : retryItem.assignee === "leader"
5015
- ? tx.getTaskWorkspace(task.id)
5016
- : tx.getWorkItemWorkspace(task.id, retryItem.id))
5017
- ?? undefined;
5018
5021
  const retryGroup = retryItem === null || previous.executionGroupId === undefined
5019
5022
  ? undefined
5020
5023
  : workItemExecutionGroupById(retryItem, previous.executionGroupId);
@@ -5029,7 +5032,7 @@ function retryRunOperation(args, store, options) {
5029
5032
  || retryLane === undefined))) {
5030
5033
  throw dataError(`AgentRun ${previous.id} execution lineage no longer matches its Work Item.`);
5031
5034
  }
5032
- const retryManagedWorkspace = retryLane === undefined ? runWorkspace : previous.workspace;
5035
+ const retryManagedWorkspace = previous.workspace;
5033
5036
  if (retryLane !== undefined) {
5034
5037
  const storedLaneWorkspace = previous.workspace === undefined
5035
5038
  ? null
@@ -5119,6 +5122,7 @@ function retryRunOperation(args, store, options) {
5119
5122
  taskId: task.id,
5120
5123
  roleName: role.name,
5121
5124
  purpose: previous.purpose,
5125
+ ...(retryManagedWorkspace === undefined ? {} : { workspace: retryManagedWorkspace }),
5122
5126
  ...(previous.workItemId === undefined ? {} : { workItemId: previous.workItemId })
5123
5127
  }, now, "controller", retryGroup?.assignment.contextSnapshotRef);
5124
5128
  return createRunInput({
@@ -5370,7 +5374,7 @@ function prepareFinalTaskReview(store, task, now, taskFinalContract, options) {
5370
5374
  const config = taskFinalReviewConfig(taskFinalContract);
5371
5375
  const latest = establishedRound;
5372
5376
  if (latest?.status === "running") {
5373
- throw usageError(`Final Task Review is still active: ${latest.id}/${latest.status}.`);
5377
+ return latest;
5374
5378
  }
5375
5379
  if (latest?.status === "pending") {
5376
5380
  return resumablePendingFinalTaskReview(store, task, latest, config, latest.taskCandidate, taskFinalContract, options);
@@ -6116,7 +6120,8 @@ export function dispatchPreparedReviewRound(taskId, reviewRoundId, store, option
6116
6120
  roleName: reviewer.name,
6117
6121
  purpose: "review",
6118
6122
  ...(item === undefined ? {} : { workItemId: item.id }),
6119
- reviewRoundId: round.id
6123
+ reviewRoundId: round.id,
6124
+ workspace: round.workspace
6120
6125
  }, now, "controller");
6121
6126
  const created = createRun(runId, taskId, reviewer.name, roleAgentSessionResumeMode(tx.getTaskRoleSessionSet(taskId, reviewer.name), effective.agentId, effective), createRunInput({
6122
6127
  source: {
@@ -6173,6 +6178,14 @@ export function dispatchPreparedReviewRound(taskId, reviewRoundId, store, option
6173
6178
  reviewBaseCommit: round.reviewBaseCommit
6174
6179
  });
6175
6180
  const runId = tx.nextRunId(taskId);
6181
+ const snapshot = freezeRunContextSnapshot(tx, {
6182
+ taskId,
6183
+ roleName: laneReviewer.name,
6184
+ purpose: "review",
6185
+ ...(item === undefined ? {} : { workItemId: item.id }),
6186
+ reviewRoundId: round.id,
6187
+ workspace: laneManagedWorkspace
6188
+ }, now, "controller", runningGroup.assignment.contextSnapshotRef);
6176
6189
  const input = createRunInput({
6177
6190
  source: {
6178
6191
  type: "yui",
@@ -6192,7 +6205,8 @@ export function dispatchPreparedReviewRound(taskId, reviewRoundId, store, option
6192
6205
  assignment: runningGroup.assignment
6193
6206
  }, null, 2)
6194
6207
  ].join("\n"),
6195
- deltaRefIds: []
6208
+ contextSnapshotRef: contextSnapshotRef(snapshot),
6209
+ deltaRefIds: contextSnapshotDeltaRefIds(tx, snapshot)
6196
6210
  });
6197
6211
  runningGroup = updateUnifiedExecutionLane(runningGroup, lane.id, {
6198
6212
  currentRunId: runId,
@@ -6226,23 +6240,12 @@ export function dispatchPreparedReviewRound(taskId, reviewRoundId, store, option
6226
6240
  tx.saveManagedWorkspace(prepared);
6227
6241
  }
6228
6242
  }
6229
- for (let index = 0; index < createdRuns.length; index += 1) {
6230
- const unboundRun = createdRuns[index];
6231
- const snapshot = freezeRunContextSnapshot(tx, {
6232
- taskId,
6233
- roleName: unboundRun.roleName,
6234
- purpose: "review",
6235
- ...(item === undefined ? {} : { workItemId: item.id }),
6236
- reviewRoundId: round.id
6237
- }, now, "controller", runningGroup.assignment.contextSnapshotRef);
6238
- const created = withRunContextSnapshot(unboundRun, contextSnapshotRef(snapshot), contextSnapshotDeltaRefIds(tx, snapshot));
6239
- createdRuns[index] = created;
6240
- const laneReviewer = requireRole(tx, taskId, unboundRun.roleName);
6243
+ for (const created of createdRuns) {
6241
6244
  tx.saveRun(created);
6242
6245
  tx.saveActiveRun(created);
6243
6246
  enqueueRoleRunDispatch(tx, {
6244
6247
  taskId,
6245
- roleName: laneReviewer.name,
6248
+ roleName: created.roleName,
6246
6249
  runId: created.id,
6247
6250
  reason: "review-requested",
6248
6251
  occurredAt: now
@@ -1,6 +1,4 @@
1
1
  import { usageError } from "../errors/cliError.js";
2
- import { GitIntegrationService } from "../integration/gitIntegrationService.js";
3
- import { createIntegrationAttempt } from "../integration/integrationAttempt.js";
4
2
  import { NodeGitWorkspace } from "../repository/gitWorkspace.js";
5
3
  import { isCompletedTaskReviewEvidence } from "../review/reviewAcceptance.js";
6
4
  import { publicationExternalKey } from "../task/publicationReference.js";
@@ -150,121 +148,6 @@ function sameTaskCandidate(left, right) {
150
148
  && left.projects.every((project, index) => (project.projectId === right.projects[index]?.projectId
151
149
  && project.commit === right.projects[index]?.commit));
152
150
  }
153
- /**
154
- * Reconcile configured remote baselines before a Task completion attempt.
155
- *
156
- * Remote resolution and fetches happen from the Task's managed worktree. A
157
- * moved remote is represented by a normal upstream Integration Attempt. The
158
- * normal check and CAS path advances only the Task clone; stable Project
159
- * checkouts are never refreshed or otherwise mutated here.
160
- */
161
- export async function reconcileTaskRemoteBaselines(taskId, store, home, options = {}) {
162
- const task = store.getTask(taskId);
163
- if (task === null)
164
- throw usageError(`Task not found: ${taskId}.`);
165
- if (task.projectBindings.length === 0) {
166
- return [];
167
- }
168
- const workspace = requireTaskWorkspace(store, task);
169
- const git = options.git ?? new NodeGitWorkspace();
170
- if (git.fetchRemoteHeadIntoWorktree === undefined) {
171
- throw usageError(`Task ${task.id} cannot verify remote baselines: managed Git workspace support is unavailable.`);
172
- }
173
- const plans = [];
174
- for (const binding of task.projectBindings) {
175
- const project = store.getProject(binding.projectId);
176
- if (project === null) {
177
- throw usageError(`Project not found for Task ${task.id}: ${binding.projectId}.`);
178
- }
179
- if (project.remoteUrl === undefined)
180
- continue;
181
- const entry = workspaceProjectEntry(workspace, project.id);
182
- if (entry === undefined || entry.access !== "write") {
183
- throw usageError(`Task ${task.id} has no writable managed main workspace for remote Project ${project.id}.`);
184
- }
185
- const currentCommit = (await git.inspect(entry.path, "HEAD")).baseCommit;
186
- if (binding.currentCommit !== currentCommit || binding.baseCommit === undefined) {
187
- throw usageError(`Project ${project.id} Task commit record does not match its authoritative main clone.`);
188
- }
189
- const remote = await fetchRemote(git, entry, project);
190
- if (remote.commit === currentCommit)
191
- continue;
192
- if (await git.isAncestor(entry.path, remote.commit, currentCommit))
193
- continue;
194
- if (!await git.isClean(entry.path)) {
195
- throw usageError(`Project ${project.id} managed Task workspace is dirty; commit or clean it before remote reconciliation.`);
196
- }
197
- plans.push({
198
- project,
199
- entry,
200
- remote,
201
- currentCommit,
202
- taskBaseCommit: binding.baseCommit
203
- });
204
- }
205
- const reconciled = [];
206
- for (const plan of plans) {
207
- const attempt = store.transaction((tx) => {
208
- const created = createIntegrationAttempt({
209
- id: tx.nextIntegrationAttemptId(task.id),
210
- taskId: task.id,
211
- projectId: plan.project.id,
212
- targetRef: plan.entry.branch,
213
- beforeCommit: plan.currentCommit,
214
- source: {
215
- kind: "upstream",
216
- branch: plan.remote.branch,
217
- remoteCommit: plan.remote.commit,
218
- taskBaseCommit: plan.taskBaseCommit,
219
- strategy: "rebase"
220
- },
221
- checkCommands: []
222
- }, options.now?.() ?? new Date());
223
- tx.saveIntegrationAttempt(task.id, created);
224
- return created;
225
- });
226
- const result = await new GitIntegrationService(home, store, git, options.now ?? (() => new Date()), options.environment, undefined, options.jobPort).integrate(task.id, attempt.id);
227
- // rr6/f3: A moved remote with non-empty checks spawns a DurableJob. This
228
- // is a pending completion outcome, not a failure: name the exact
229
- // Integration and Job and the exact continuation command (mirroring the
230
- // `task integration` checks-running message) so the caller can resume the
231
- // same remote-reconciliation attempt instead of being blocked by the
232
- // preflight's active-job/unresolved-Integration gates.
233
- if (result.status === "checks-running") {
234
- throw usageError(`Remote baseline reconciliation for ${task.id}/${plan.project.id} is running checks as `
235
- + `Integration ${result.attempt.id} (DurableJob ${result.job.id}); run `
236
- + `'yui task integration continue ${task.id}/${result.attempt.id}' when the job finishes, `
237
- + `then retry task complete.`);
238
- }
239
- if (result.status !== "committed" || result.attempt.candidateCommit === undefined) {
240
- const detail = result.attempt.checks?.find(({ outcome }) => outcome === "failed")?.details
241
- ?? result.attempt.conflict?.summary
242
- ?? result.attempt.status;
243
- throw usageError(`Remote baseline reconciliation failed for ${task.id}/${plan.project.id}: ${detail}`);
244
- }
245
- reconciled.push({
246
- projectId: plan.project.id,
247
- remote: plan.remote,
248
- fromCommit: plan.currentCommit,
249
- toCommit: result.attempt.candidateCommit,
250
- integrationId: attempt.id
251
- });
252
- }
253
- return reconciled;
254
- }
255
- async function fetchRemote(git, entry, project) {
256
- try {
257
- return await git.fetchRemoteHeadIntoWorktree({
258
- repositoryPath: entry.path,
259
- remoteUrl: project.remoteUrl,
260
- branch: project.developmentBranch
261
- });
262
- }
263
- catch (error) {
264
- throw usageError(`Project ${project.id} remote target could not be resolved; completion is fail-closed: `
265
- + `${error instanceof Error ? error.message : String(error)}`);
266
- }
267
- }
268
151
  function requireTaskWorkspace(store, task) {
269
152
  const workspace = store.getTaskWorkspace(task.id);
270
153
  if (workspace === null || workspace.owner.type !== "task") {
@@ -18,7 +18,7 @@ export function taskRoleHostDiagnostic(host) {
18
18
  const delivery = snapshot.eventDelivery;
19
19
  return [
20
20
  `Provider Host=${snapshot.state}`,
21
- delivery === undefined ? "event delivery=unreported (legacy Host)" :
21
+ delivery === undefined ? "event delivery=unreported" :
22
22
  `pending facts=${delivery.pending}; native terminals awaiting acknowledgement=${delivery.pendingTerminals}`,
23
23
  delivery?.failure === undefined ? undefined :
24
24
  `reporting failure (${delivery.failure.stage}, ${delivery.failure.observedAt}): ${delivery.failure.detail}`,