@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.
- package/ARCHITECTURE.md +12 -0
- package/ARCHITECTURE.zh-CN.md +8 -0
- package/README.md +3 -0
- package/dist/agent/managedRuntimeEnvironment.js +0 -4
- package/dist/agentRun/agentRun.js +7 -17
- package/dist/cli/agentConfigurationPicker.js +24 -21
- package/dist/cli/commandCatalog.js +18 -10
- package/dist/cli/roleWizard.js +41 -30
- package/dist/cli/updateCommand.js +35 -13
- package/dist/cli/updateOrchestrator.js +73 -33
- package/dist/cli/updatePorts.js +40 -17
- package/dist/cli.js +35 -26
- package/dist/commands/controllerCommands.js +1 -1
- package/dist/commands/executionAuditCommands.js +2 -2
- package/dist/commands/projectCommands.js +1 -1
- package/dist/commands/releaseCommands.js +9 -38
- package/dist/commands/taskCommands.js +84 -81
- package/dist/commands/taskCompletionGate.js +0 -117
- package/dist/commands/taskRoleRuntimeStatus.js +1 -1
- package/dist/commands/taskUpstreamCommands.js +93 -54
- package/dist/context/runContextPack.js +30 -54
- package/dist/context/runInputContract.js +9 -0
- package/dist/context/sessionBootstrapManifest.js +11 -19
- package/dist/controller/agentHostObservation.js +4 -2
- package/dist/controller/controller.js +8 -6
- package/dist/controller/fileSchedulerStoreAdapter.js +85 -18
- package/dist/controller/globalInputDelivery.js +28 -7
- package/dist/controller/globalRuntimeAttention.js +34 -0
- package/dist/controller/operatorNotification.js +31 -0
- package/dist/controller/providerRetryAdmission.js +3 -1
- package/dist/controller/providerRetryDelivery.js +10 -3
- package/dist/controller/runtime.js +1 -27
- package/dist/controller/sessionOwnerReconciliation.js +42 -24
- package/dist/controller/structuredProviderObservation.js +27 -0
- package/dist/controller/updateReconciliation.js +72 -20
- package/dist/doctor/doctor.js +2 -1
- package/dist/executor/agentAdapter.js +28 -96
- package/dist/executor/agentConfigurationCatalog.js +13 -68
- package/dist/executor/agentConfigurationFields.js +120 -0
- package/dist/executor/agentConfigurationProbe.js +55 -80
- package/dist/executor/agentExecutor.js +5 -2
- package/dist/executor/executorRegistry.js +0 -9
- package/dist/executor/fileRoleLaunchPlanner.js +12 -11
- package/dist/interaction/operatorPresentation.js +2 -1
- package/dist/message/messageContinuation.js +8 -9
- package/dist/observability/executionAudit.js +1 -10
- package/dist/observability/runtimeIdentity.js +0 -23
- package/dist/output/agentConfigurationPresentation.js +4 -2
- package/dist/release/releaseHandover.js +2 -2
- package/dist/release/releaseIdempotencyStore.js +0 -23
- package/dist/release/releaseWorkflowPorts.js +8 -4
- package/dist/repository/gitWorkspace.js +66 -19
- package/dist/repository/taskWorkspacePreparer.js +75 -68
- package/dist/resources/resourceRegistry.js +90 -44
- package/dist/resources/sqliteResourceRegistry.js +3 -5
- package/dist/runtime/acpSession.js +21 -5
- package/dist/runtime/agentEndpoint.js +4 -1
- package/dist/runtime/agentHost.js +22 -62
- package/dist/runtime/agentHostCleanup.js +85 -0
- package/dist/runtime/agentHostProtocol.js +1 -1
- package/dist/runtime/builtinAgentDrivers.js +46 -119
- package/dist/runtime/builtinTranscriptObserver.js +10 -6
- package/dist/runtime/codexAppServerRuntime.js +55 -89
- package/dist/runtime/jsonLineChannel.js +35 -7
- package/dist/runtime/providerContinuationReconciliationService.js +42 -3
- package/dist/runtime/providerRetry.js +15 -0
- package/dist/runtime/providerRuntimeReconciler.js +12 -2
- package/dist/runtime/structuredProviderHost.js +106 -81
- package/dist/scheduler/activeRoleRunDelivery.js +5 -1
- package/dist/scheduler/operatorInputNotificationProcessor.js +7 -17
- package/dist/storage/upgrade/upgradeOrchestrator.js +0 -10
- package/dist/task/nextAction.js +33 -23
- package/dist/task/task.js +2 -1
- package/dist/web/assets/assetManifest.js +2 -0
- package/dist/web/assets/client/app.js +72 -3
- package/dist/web/assets/client/components.js +2 -1
- package/dist/web/assets/client/i18n.js +2 -0
- package/dist/web/assets/client/taskSummary.js +345 -0
- package/dist/web/assets/client/taskSurface.js +44 -26
- package/dist/web/assets/client/view.js +33 -0
- package/dist/web/assets/shell.js +1 -0
- package/dist/web/assets/styles/cards.js +21 -0
- package/dist/web/webServer.js +39 -5
- package/dist/web/webSessions.js +165 -0
- package/dist/web/webSnapshot.js +23 -0
- package/dist/web/webTaskSurface.js +23 -0
- package/docs/managed-turn-and-session-runtime.md +31 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +23 -0
- package/docs/observability/README.md +47 -0
- package/docs/observability/README.zh-CN.md +37 -0
- package/docs/project-refresh.md +9 -0
- package/docs/project-refresh.zh-CN.md +8 -0
- package/docs/provider-retry.md +35 -0
- package/docs/release-workflow.md +124 -20
- package/docs/release-workflow.zh-CN.md +103 -14
- package/docs/roles-and-configuration.md +30 -0
- package/docs/roles-and-configuration.zh-CN.md +20 -0
- package/docs/task-delivery.md +109 -0
- package/docs/task-delivery.zh-CN.md +80 -0
- package/docs/task-discovery.md +9 -0
- package/docs/task-discovery.zh-CN.md +6 -0
- package/docs/testing/verification-levels.md +29 -11
- package/docs/testing/verification-levels.zh-CN.md +25 -7
- package/i18n/README.zh-CN.md +2 -0
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +11 -0
- package/skills/yui-leader/references/execution.md +22 -0
- package/skills/yui-leader/references/planning.md +6 -2
- package/skills/yui-operator/SKILL.md +45 -13
- package/skills/yui-operator/references/task-delivery.md +99 -0
- package/skills/yui-runtime/SKILL.md +5 -3
- package/skills/yui-runtime/references/publication.md +56 -5
- package/skills/yui-runtime/references/recovery.md +12 -2
- 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
|
|
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,
|
|
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
|
|
243
|
-
* baselines
|
|
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
|
|
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
|
-
//
|
|
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
|
|
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
|
|
1179
|
-
|
|
1180
|
-
:
|
|
1181
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
3508
|
-
|
|
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:
|
|
3535
|
+
runId: run.id,
|
|
3524
3536
|
reason: "turn-dispatched",
|
|
3525
3537
|
occurredAt: now
|
|
3526
3538
|
});
|
|
3527
|
-
recordTaskEvent(tx, task.id, "run.dispatched", runLaunchEventPayload(
|
|
3528
|
-
return { kind: "direct", runs: [
|
|
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
|
-
|
|
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(
|
|
3623
|
-
tx.saveActiveRun(
|
|
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:
|
|
3640
|
+
runId: run.id,
|
|
3628
3641
|
reason: "turn-dispatched",
|
|
3629
3642
|
occurredAt: now
|
|
3630
3643
|
});
|
|
3631
|
-
recordTaskEvent(tx, task.id, "run.dispatched", runLaunchEventPayload(
|
|
3632
|
-
return
|
|
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,
|
|
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>
|
|
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],
|
|
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) =>
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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:
|
|
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
|
|
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}`,
|