@zq-silk/yui 0.15.11 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +11 -6
- package/ARCHITECTURE.zh-CN.md +8 -4
- package/README.md +13 -5
- package/dist/agentRun/agentRun.js +3 -0
- package/dist/artifacts/artifactCommitLock.js +16 -55
- package/dist/artifacts/taskArtifactRepository.js +3 -3
- package/dist/cli/agentConfigurationPicker.js +1 -1
- package/dist/cli/commandCatalog.js +92 -48
- package/dist/cli/completion.js +18 -18
- package/dist/cli/completionWizard.js +1 -1
- package/dist/cli/dynamicCompletion.js +1 -1
- package/dist/cli/interactionPolicy.js +11 -3
- package/dist/cli/invocationAuthority.js +64 -0
- package/dist/cli/managedDiagnostics.js +2 -2
- package/dist/cli/parseRepeatable.js +35 -0
- package/dist/cli/updatePorts.js +26 -5
- package/dist/cli.js +1303 -1235
- package/dist/commands/agentCommands.js +4 -4
- package/dist/commands/capabilityCommands.js +1 -1
- package/dist/commands/configCommands.js +6 -57
- package/dist/commands/configOverview.js +2 -2
- package/dist/commands/durableJobCommands.js +12 -6
- package/dist/commands/executionAuditCommands.js +10 -0
- package/dist/commands/globalRoleCommands.js +78 -29
- package/dist/commands/grantCommands.js +0 -3
- package/dist/commands/jobCommands.js +1 -4
- package/dist/commands/operatorCommands.js +3 -3
- package/dist/commands/projectCommands.js +45 -25
- package/dist/commands/resourcesCommands.js +10 -40
- package/dist/commands/roleConfiguration.js +2 -6
- package/dist/commands/taskActivationCommands.js +4 -8
- package/dist/commands/taskAgentCapabilities.js +9 -0
- package/dist/commands/taskCommandSupport.js +155 -0
- package/dist/commands/taskCommandTypes.js +1 -0
- package/dist/commands/taskCommands.js +355 -732
- package/dist/commands/taskCompletionGate.js +1 -1
- package/dist/commands/taskExecutionCommands.js +1 -1
- package/dist/commands/taskFactCommands.js +325 -0
- package/dist/commands/taskInputCommands.js +12 -42
- package/dist/commands/taskIntegrationCommands.js +20 -58
- package/dist/commands/taskNextActionCommand.js +7 -6
- package/dist/commands/taskPublicationAdoptCommand.js +127 -0
- package/dist/commands/taskPublicationCommands.js +12 -3
- package/dist/commands/taskPublicationVerifyCommand.js +24 -40
- package/dist/commands/taskRemoteDeliveryCommand.js +5 -86
- package/dist/commands/taskUpstreamCommands.js +19 -8
- package/dist/commands/workflowCommands.js +6 -1
- package/dist/completion/completionInstaller.js +26 -26
- package/dist/completion/completionState.js +26 -26
- package/dist/completion/fileCompletionManager.js +6 -11
- package/dist/config/configCatalog.js +0 -2
- package/dist/config/timeZone.js +14 -0
- package/dist/config/yuiConfig.js +0 -29
- package/dist/context/runContextPack.js +5 -3
- package/dist/context/taskCatalog.js +185 -0
- package/dist/context/taskContext.js +152 -151
- package/dist/context/wakeRunReferences.js +11 -0
- package/dist/controller/agentCapabilities.js +58 -0
- package/dist/controller/agentRuntimeObserver.js +6 -11
- package/dist/controller/clientRuntime.js +22 -14
- package/dist/controller/controller.js +20 -24
- package/dist/controller/fileSchedulerStoreAdapter.js +191 -225
- package/dist/controller/globalInputDelivery.js +13 -0
- package/dist/controller/jobClient.js +4 -4
- package/dist/controller/jobControl.js +60 -25
- package/dist/controller/jobSupervisor.js +4 -4
- package/dist/controller/providerRetryAdmission.js +100 -0
- package/dist/controller/providerRetryDelivery.js +218 -0
- package/dist/controller/runtime.js +85 -43
- package/dist/controller/runtimeEventProcessor.js +0 -5
- package/dist/controller/sessionOwnerReconciliation.js +5 -0
- package/dist/controller/taskAgentError.js +35 -0
- package/dist/coordination/workMailboxQueue.js +2 -24
- package/dist/core/controllerClient.js +2 -2
- package/dist/core/fileLockOwner.js +74 -0
- package/dist/decision/decision.js +17 -0
- package/dist/doctor/doctor.js +18 -9
- package/dist/event/taskEvent.js +12 -0
- package/dist/execution/workItemExecutionProjection.js +2 -2
- package/dist/executor/agentCapabilityConfig.js +43 -0
- package/dist/executor/agentConfigurationCatalog.js +49 -11
- package/dist/executor/agentExecutor.js +5 -8
- package/dist/executor/fileRoleLaunchPlanner.js +11 -53
- package/dist/executor/taskAgentCapabilities.js +64 -0
- package/dist/integration/deliveryObligation.js +1 -69
- package/dist/integration/gitIntegrationService.js +79 -90
- package/dist/integration/integrationAttempt.js +3 -14
- package/dist/integration/integrationSourceApplication.js +4 -12
- package/dist/integration/manifestTags.js +2 -2
- package/dist/job/durableJob.js +4 -25
- package/dist/job/jobAssignmentScope.js +22 -0
- package/dist/job/jobOperation.js +16 -0
- package/dist/job/jobRunner.js +2 -1
- package/dist/job/stepDirectory.js +15 -0
- package/dist/kernel/builtinCapabilities.js +15 -11
- package/dist/kernel/kernelPorts.js +1 -17
- package/dist/lifecycle/exactRunTerminalization.js +5 -10
- package/dist/message/globalProviderRetry.js +15 -0
- package/dist/message/inputControlResolution.js +3 -4
- package/dist/message/message.js +17 -20
- package/dist/message/messageContinuation.js +1 -1
- package/dist/milestone/milestone.js +11 -0
- package/dist/observability/executionAudit.js +19 -0
- package/dist/observability/orchestrationMetrics.js +24 -1
- package/dist/observability/runtimeIdentity.js +1 -17
- package/dist/output/agentConfigurationPresentation.js +2 -0
- package/dist/output/timePresentation.js +1 -14
- package/dist/plugins/pluginService.js +12 -4
- package/dist/release/releaseWorkflowPorts.js +45 -96
- package/dist/release/runtimeRelease.js +9 -15
- package/dist/repository/gitWorkspace.js +371 -105
- package/dist/repository/projectMaintenanceLock.js +98 -82
- package/dist/repository/taskBaseFreshness.js +1 -1
- package/dist/repository/taskWorkspaceCoordinator.js +82 -144
- package/dist/repository/taskWorkspacePreparer.js +113 -47
- package/dist/repository/workspaceCleanupInspection.js +187 -0
- package/dist/resources/autoResourceGc.js +4 -77
- package/dist/resources/liveReferences.js +7 -54
- package/dist/resources/resourceDiscovery.js +5 -118
- package/dist/resources/resourceGc.js +233 -181
- package/dist/resources/resourceRegistrar.js +5 -4
- package/dist/resources/resourceRegistry.js +3 -37
- package/dist/resources/resourceRegistryStore.js +13 -36
- package/dist/resources/sqliteResourceRegistry.js +43 -26
- package/dist/review/deltaRecheck.js +1 -1
- package/dist/review/reviewAcceptance.js +1 -1
- package/dist/review/reviewDecision.js +1 -1
- package/dist/review/reviewRound.js +8 -7
- package/dist/review/taskFinalReviewContractResolution.js +1 -1
- package/dist/runtime/acpProtocol.js +4 -51
- package/dist/runtime/acpSession.js +10 -75
- package/dist/runtime/acpSessionConfiguration.js +1 -8
- package/dist/runtime/agentEndpoint.js +3 -2
- package/dist/runtime/agentError.js +5 -3
- package/dist/runtime/agentFailureContext.js +43 -0
- package/dist/runtime/agentHost.js +42 -25
- package/dist/runtime/builtinAgentErrorMappers.js +91 -0
- package/dist/runtime/codexAppServerRuntime.js +34 -3
- package/dist/runtime/codexInteractiveHost.js +2 -2
- package/dist/runtime/index.js +0 -1
- package/dist/runtime/managedCaller.js +21 -1
- package/dist/runtime/providerControl.js +5 -1
- package/dist/runtime/providerErrors.js +38 -0
- package/dist/runtime/providerRetry.js +198 -0
- package/dist/runtime/providerRuntimeIdentity.js +28 -2
- package/dist/runtime/runtimeObservation.js +0 -5
- package/dist/runtime/runtimeSessionCandidate.js +2 -3
- package/dist/runtime/sessionOwnerIdentity.js +1 -1
- package/dist/runtime/sessionTokenMetrics.js +15 -5
- package/dist/runtime/structuredProviderHost.js +10 -43
- package/dist/runtime/taskUsageMetrics.js +275 -0
- package/dist/runtime/tmuxAdapters.js +6 -8
- package/dist/scheduler/activeRoleRunDelivery.js +19 -7
- package/dist/scheduler/leaderWakeupProcessor.js +24 -6
- package/dist/scheduler/operatorEvent.js +12 -20
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +5 -8
- package/dist/scheduler/roleRunLiveness.js +4 -4
- package/dist/scheduler/roleRunStall.js +16 -23
- package/dist/scheduler/taskExecutionProjection.js +49 -36
- package/dist/scheduler/taskObservabilityProjection.js +6 -45
- package/dist/scheduler/taskWake.js +5 -10
- package/dist/scheduler/wakeReason.js +2 -0
- package/dist/scheduler/wakeupQueue.js +2 -4
- package/dist/setup/setupCommand.js +1 -1
- package/dist/storage/contextRecords.js +106 -0
- package/dist/storage/currentTaskStore.js +1 -1
- package/dist/storage/homeLayout.js +13 -17
- package/dist/storage/migrations/agentFailureContext.js +22 -0
- package/dist/storage/migrations/currentInputContract.js +86 -0
- package/dist/storage/migrations/currentRuntimeContract.js +228 -0
- package/dist/storage/migrations/historicalVerificationPlan.js +35 -0
- package/dist/storage/migrations/integrationContinuation.js +5 -4
- package/dist/storage/migrations/narrowAgentFailureContext.js +65 -0
- package/dist/storage/migrations/notificationOnlyWakes.js +74 -0
- package/dist/storage/migrations/verificationPlanV1.js +162 -0
- package/dist/storage/migrations/verificationPolicy.js +74 -0
- package/dist/storage/migrations/workItemHistory.js +46 -0
- package/dist/storage/persistenceWorker.js +12 -4
- package/dist/storage/recordValidation.js +87 -0
- package/dist/storage/sqliteSchema.js +173 -1
- package/dist/storage/sqliteStore.js +172 -161
- package/dist/storage/storageSchema.js +2 -14
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +16 -7
- package/dist/storage/taskCatalog.js +123 -0
- package/dist/storage/taskStore.js +5 -7
- package/dist/storage/upgrade/upgradeOrchestrator.js +25 -37
- package/dist/task/archiveDiagnostics.js +1 -0
- package/dist/task/archivePreflight.js +124 -0
- package/dist/task/completionReadiness.js +5 -24
- package/dist/task/draftPlan.js +0 -53
- package/dist/task/nextAction.js +7 -13
- package/dist/task/publicationAdoption.js +56 -0
- package/dist/task/publicationReference.js +10 -0
- package/dist/task/remoteDelivery.js +31 -16
- package/dist/task/remoteDeliveryService.js +89 -0
- package/dist/task/taskActivation.js +2 -25
- package/dist/task/taskActivationService.js +0 -2
- package/dist/task/taskRecordReference.js +0 -1
- package/dist/task/taskSubmission.js +3 -14
- package/dist/telemetry/sqliteTelemetryBatch.js +29 -0
- package/dist/telemetry/sqliteTelemetryStore.js +49 -49
- package/dist/telemetry/telemetryWiring.js +4 -3
- package/dist/tmux/tmuxManager.js +29 -20
- package/dist/verification/gateArtifact.js +15 -24
- package/dist/verification/gateArtifactStore.js +14 -7
- package/dist/verification/verificationGateService.js +29 -88
- package/dist/verification/verificationPlan.js +27 -72
- package/dist/web/assets/client/app.js +92 -17
- package/dist/web/assets/client/components.js +55 -13
- package/dist/web/assets/client/i18n.js +72 -4
- package/dist/web/assets/client/taskSurface.js +6 -5
- package/dist/web/assets/client/view.js +35 -7
- package/dist/web/assets/shell.js +6 -0
- package/dist/web/assets/styles/layout.js +7 -0
- package/dist/web/webServer.js +12 -3
- package/dist/web/webSnapshot.js +14 -85
- package/dist/web/webTaskSurface.js +17 -46
- package/dist/workItem/workItem.js +1 -12
- package/dist/workspace/cleanupInspection.js +63 -0
- package/dist/workspace/workItemChangeSetManager.js +110 -50
- package/docs/agent-result-consumption.md +4 -0
- package/docs/agent-result-consumption.zh-CN.md +3 -0
- package/docs/agent-runtime-drivers.md +7 -0
- package/docs/agent-runtime-drivers.zh-CN.md +5 -0
- package/docs/architecture/README.md +2 -0
- package/docs/architecture/README.zh-CN.md +3 -1
- package/docs/architecture/capabilities-and-resources.md +42 -5
- package/docs/architecture/capabilities-and-resources.zh-CN.md +33 -3
- package/docs/managed-turn-and-session-runtime.md +121 -1
- package/docs/managed-turn-and-session-runtime.zh-CN.md +96 -2
- package/docs/observability/README.md +62 -0
- package/docs/observability/README.zh-CN.md +47 -0
- package/docs/plugin-sdk.md +4 -2
- package/docs/project-refresh.md +77 -0
- package/docs/project-refresh.zh-CN.md +59 -0
- package/docs/provider-retry.md +70 -0
- package/docs/provider-runtime.md +3 -1
- package/docs/provider-runtime.zh-CN.md +4 -2
- package/docs/release-workflow.md +190 -7
- package/docs/release-workflow.zh-CN.md +139 -5
- package/docs/roles-and-configuration.md +29 -0
- package/docs/roles-and-configuration.zh-CN.md +21 -0
- package/docs/sqlite-control-plane-design.md +16 -3
- package/docs/sqlite-control-plane-design.zh-CN.md +13 -2
- package/docs/task-dag-semantics.md +3 -3
- package/docs/task-dag-semantics.zh-CN.md +2 -2
- package/docs/task-delivery.md +223 -17
- package/docs/task-delivery.zh-CN.md +171 -14
- package/docs/task-discovery.md +101 -0
- package/docs/task-discovery.zh-CN.md +85 -0
- package/docs/testing/verification-levels.md +161 -9
- package/docs/testing/verification-levels.zh-CN.md +116 -9
- package/i18n/README.zh-CN.md +13 -7
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +5 -0
- package/skills/yui-leader/references/execution.md +3 -2
- package/skills/yui-leader/references/integration.md +9 -5
- package/skills/yui-leader/references/planning.md +9 -3
- package/skills/yui-operator/SKILL.md +24 -8
- package/skills/yui-reviewer/SKILL.md +4 -0
- package/skills/yui-runtime/SKILL.md +17 -2
- package/skills/yui-runtime/references/publication.md +26 -4
- package/skills/yui-runtime/references/recovery.md +71 -0
- package/dist/agent/agentRegistry.js +0 -10
- package/dist/agentRun/runIdentity.js +0 -22
- package/dist/commands/deliveryGuardPreflight.js +0 -30
- package/dist/commands/taskIntegrationQueueCommands.js +0 -226
- package/dist/commands/taskOverviewCommand.js +0 -376
- package/dist/completion/completionWizard.js +0 -125
- package/dist/context/dispatchContext.js +0 -110
- package/dist/context/wakeNotification.js +0 -144
- package/dist/integration/integrationCheckEvidenceReuse.js +0 -53
- package/dist/integration/integrationQueueEntry.js +0 -191
- package/dist/integration/integrationQueueService.js +0 -810
- package/dist/release/fakeReleasePorts.js +0 -55
- package/dist/runtime/sessionOwnerRegistry.js +0 -137
- package/dist/task/deliveryGuard.js +0 -226
- /package/dist/{commands/taskActor.js → task/taskAuthority.js} +0 -0
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
import { usageError } from "../errors/cliError.js";
|
|
2
|
-
import { isRoleRunStalled, latestStallProgressAt } from "../scheduler/roleRunStall.js";
|
|
3
|
-
import { formatTimestamp } from "../output/timePresentation.js";
|
|
4
|
-
import { pendingWakeupProjection } from "../storage/taskStore.js";
|
|
5
|
-
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
6
|
-
import { projectTaskExecutionFromFacts } from "../scheduler/taskExecutionProjection.js";
|
|
7
|
-
import { resolveRuntimeHealth } from "../config/yuiConfig.js";
|
|
8
|
-
import { projectNextAction } from "../task/nextAction.js";
|
|
9
|
-
import { projectTaskRemoteDeliveryFromStore } from "./taskRemoteDeliveryCommand.js";
|
|
10
|
-
export function parseTaskListOptions(args) {
|
|
11
|
-
const allowed = new Set(["--all", "--verbose"]);
|
|
12
|
-
if (args.some((argument) => !allowed.has(argument))
|
|
13
|
-
|| new Set(args).size !== args.length) {
|
|
14
|
-
throw usageError("Task list usage: yui task list [--all] [--verbose].");
|
|
15
|
-
}
|
|
16
|
-
return {
|
|
17
|
-
all: args.includes("--all"),
|
|
18
|
-
verbose: args.includes("--verbose")
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
export function buildTaskOverview(store, options, now = new Date()) {
|
|
22
|
-
const runtimeHealthPolicy = resolveRuntimeHealth(store.getConfig().runtimeHealth);
|
|
23
|
-
const tasks = store.listTasks()
|
|
24
|
-
.filter((task) => options.all || task.status !== "archived")
|
|
25
|
-
.map((task) => buildTaskOverviewEntry(task, store, now, runtimeHealthPolicy));
|
|
26
|
-
return { tasks };
|
|
27
|
-
}
|
|
28
|
-
export function renderTaskOverview(result, options, timeZone, width = defaultTableWidth()) {
|
|
29
|
-
if (result.tasks.length === 0)
|
|
30
|
-
return "No tasks found.\n";
|
|
31
|
-
const title = options.all ? "Tasks (all)" : "Tasks (unarchived)";
|
|
32
|
-
const output = renderTable(title, [
|
|
33
|
-
{ header: "Task", minWidth: 8, maxWidth: 20 },
|
|
34
|
-
{ header: "Title", minWidth: 10, maxWidth: 46 },
|
|
35
|
-
{ header: "Lifecycle", minWidth: 9, maxWidth: 14 },
|
|
36
|
-
{ header: "Leader", minWidth: 12, maxWidth: 48 },
|
|
37
|
-
{ header: "Summary updated", minWidth: 16, maxWidth: 28 },
|
|
38
|
-
{ header: "Work", minWidth: 8, maxWidth: 38 },
|
|
39
|
-
{ header: "Blockers", minWidth: 9, maxWidth: 42 },
|
|
40
|
-
{ header: "Execution", minWidth: 14, maxWidth: 34 },
|
|
41
|
-
{ header: "Delivery", minWidth: 12, maxWidth: 28 },
|
|
42
|
-
{ header: "Next action / owner", minWidth: 16, maxWidth: 42 }
|
|
43
|
-
], result.tasks.map((task) => [
|
|
44
|
-
task.id,
|
|
45
|
-
task.title,
|
|
46
|
-
task.status,
|
|
47
|
-
leaderCell(task),
|
|
48
|
-
task.summaryUpdatedAt === null
|
|
49
|
-
? "missing"
|
|
50
|
-
: formatTimestamp(task.summaryUpdatedAt, timeZone),
|
|
51
|
-
workCell(task.work.counts),
|
|
52
|
-
blockersCell(task.blockers),
|
|
53
|
-
`${task.execution.status} / ${task.execution.owner}`,
|
|
54
|
-
deliveryCell(task.remoteDelivery),
|
|
55
|
-
nextCell(task.next)
|
|
56
|
-
]), width);
|
|
57
|
-
if (!options.verbose)
|
|
58
|
-
return `${output}\n`;
|
|
59
|
-
return `${output}\n\n${renderVerboseDetails(result.tasks, timeZone)}\n`;
|
|
60
|
-
}
|
|
61
|
-
function buildTaskOverviewEntry(task, store, now, runtimeHealthPolicy) {
|
|
62
|
-
const brief = store.getTaskBrief(task.id);
|
|
63
|
-
const roles = store.listRoles(task.id);
|
|
64
|
-
const leaderRole = roles.find((role) => role.name === "leader") ?? null;
|
|
65
|
-
const workItems = store.listWorkItems(task.id);
|
|
66
|
-
const inputRequests = store.listInputRequests(task.id);
|
|
67
|
-
const openInputRequests = inputRequests.filter((request) => request.status === "open");
|
|
68
|
-
const runs = store.listRuns(task.id);
|
|
69
|
-
const events = store.listEvents(task.id);
|
|
70
|
-
const leaderFailure = store.getLeaderFailure(task.id);
|
|
71
|
-
const leaderMailbox = store.getWorkMailbox({ kind: "role", taskId: task.id, roleName: "leader" });
|
|
72
|
-
const pendingWakeup = pendingWakeupProjection(leaderMailbox);
|
|
73
|
-
const reviewRounds = store.listReviewRounds(task.id);
|
|
74
|
-
const changeSets = store.listChangeSets(task.id);
|
|
75
|
-
const integrations = store.listIntegrationAttempts(task.id);
|
|
76
|
-
const roleSessions = roles.flatMap((role) => {
|
|
77
|
-
const session = store.getRoleSession(task.id, role.name);
|
|
78
|
-
return session === null ? [] : [{ roleName: role.name, ...session }];
|
|
79
|
-
});
|
|
80
|
-
const providerRuns = new Map(roles.map((role) => [role.name, store.getTaskRoleSessionSet(task.id, role.name)?.providerBinding?.run]));
|
|
81
|
-
const runDelivery = Object.fromEntries(runs.map((run) => {
|
|
82
|
-
const native = providerRuns.get(run.roleName);
|
|
83
|
-
return [run.id, native?.runId === run.id ? native.status : "unobserved"];
|
|
84
|
-
}));
|
|
85
|
-
const attention = collectAttention(task, runs, events, leaderFailure);
|
|
86
|
-
const blockers = collectBlockers(workItems, openInputRequests, attention);
|
|
87
|
-
const leader = {
|
|
88
|
-
role: "leader",
|
|
89
|
-
roleStatus: leaderRole === null
|
|
90
|
-
? "missing"
|
|
91
|
-
: providerRuns.get("leader")?.status === "accepted" ? "running"
|
|
92
|
-
: roleSessions.some((session) => session.roleName === "leader") ? "unknown" : "idle",
|
|
93
|
-
summary: brief?.leaderSummary ?? null,
|
|
94
|
-
currentFocus: brief?.currentFocus ?? null,
|
|
95
|
-
updatedAt: brief?.updatedAt ?? null,
|
|
96
|
-
updatedBy: brief?.updatedBy ?? null,
|
|
97
|
-
summaryStatus: brief === null ? "missing" : "available"
|
|
98
|
-
};
|
|
99
|
-
const counts = countWorkItems(workItems);
|
|
100
|
-
const runtimeRuns = runs
|
|
101
|
-
.filter((run) => run.status === "active")
|
|
102
|
-
.map((run) => ({
|
|
103
|
-
id: run.id,
|
|
104
|
-
roleName: run.roleName,
|
|
105
|
-
status: run.status,
|
|
106
|
-
runtime: runDelivery[run.id],
|
|
107
|
-
createdAt: run.createdAt,
|
|
108
|
-
updatedAt: run.updatedAt
|
|
109
|
-
}));
|
|
110
|
-
const runtime = {
|
|
111
|
-
activeRuns: runtimeRuns,
|
|
112
|
-
activeRunCount: runtimeRuns.length,
|
|
113
|
-
pendingDeliveryCount: runtimeRuns.filter((run) => run.runtime !== "accepted").length
|
|
114
|
-
};
|
|
115
|
-
// Fold the execution projection from the facts already read above instead of
|
|
116
|
-
// reading the store a second time for the same unchanged revision.
|
|
117
|
-
const execution = projectTaskExecutionFromFacts({
|
|
118
|
-
task,
|
|
119
|
-
roles,
|
|
120
|
-
runs,
|
|
121
|
-
runDelivery,
|
|
122
|
-
workItems,
|
|
123
|
-
inputRequests,
|
|
124
|
-
reviewRounds,
|
|
125
|
-
changeSets,
|
|
126
|
-
integrations,
|
|
127
|
-
events,
|
|
128
|
-
brief,
|
|
129
|
-
pendingWakeup,
|
|
130
|
-
leaderMailbox,
|
|
131
|
-
leaderFailure,
|
|
132
|
-
roleSessions,
|
|
133
|
-
contextSnapshots: store.listContextSnapshots(task.id),
|
|
134
|
-
now,
|
|
135
|
-
runtimeHealthPolicy
|
|
136
|
-
});
|
|
137
|
-
const nextActionFacts = store.readNextActionFacts(task.id);
|
|
138
|
-
if (nextActionFacts === null) {
|
|
139
|
-
throw new Error(`Task disappeared while building its overview: ${task.id}.`);
|
|
140
|
-
}
|
|
141
|
-
const next = overviewNextAction(task, workItems, execution, projectNextAction({
|
|
142
|
-
...nextActionFacts,
|
|
143
|
-
currentTaskReviewCandidate: null,
|
|
144
|
-
executionGroups: execution.executionGroups
|
|
145
|
-
}));
|
|
146
|
-
const persistedCandidate = task.status === "active" || task.status === "cancelled"
|
|
147
|
-
? taskRemoteDeliveryCandidate(task)
|
|
148
|
-
: null;
|
|
149
|
-
const remoteDelivery = projectTaskRemoteDeliveryFromStore(store, task, persistedCandidate);
|
|
150
|
-
return {
|
|
151
|
-
...task,
|
|
152
|
-
brief,
|
|
153
|
-
leader,
|
|
154
|
-
leaderSummary: leader.summary,
|
|
155
|
-
currentFocus: leader.currentFocus,
|
|
156
|
-
summaryUpdatedAt: leader.updatedAt,
|
|
157
|
-
summaryUpdatedBy: leader.updatedBy,
|
|
158
|
-
summaryStatus: leader.summaryStatus,
|
|
159
|
-
work: { counts, items: workItems },
|
|
160
|
-
input: { open: openInputRequests, openCount: openInputRequests.length },
|
|
161
|
-
attention,
|
|
162
|
-
attentionCount: attention.length,
|
|
163
|
-
blockers,
|
|
164
|
-
next,
|
|
165
|
-
nextAction: next?.action ?? null,
|
|
166
|
-
nextOwner: next?.owner ?? null,
|
|
167
|
-
runtime,
|
|
168
|
-
execution,
|
|
169
|
-
remoteDelivery
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
function collectAttention(task, runs, events, failure) {
|
|
173
|
-
const items = [];
|
|
174
|
-
if (failure !== null) {
|
|
175
|
-
items.push({
|
|
176
|
-
kind: "leader-recovery",
|
|
177
|
-
id: `leader-recovery:${task.id}`,
|
|
178
|
-
status: "failed",
|
|
179
|
-
owner: "operator",
|
|
180
|
-
summary: failure.message,
|
|
181
|
-
updatedAt: failure.lastFailedAt
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
for (const run of runs) {
|
|
185
|
-
if (run.roleName !== "leader"
|
|
186
|
-
|| run.status !== "active"
|
|
187
|
-
|| !isRoleRunStalled(events, run.id))
|
|
188
|
-
continue;
|
|
189
|
-
const progressAt = latestStallProgressAt(events, run.id) ?? run.updatedAt;
|
|
190
|
-
items.push({
|
|
191
|
-
kind: "leader-stalled",
|
|
192
|
-
id: `leader-stall:${run.id}:${progressAt}`,
|
|
193
|
-
status: "needs-attention",
|
|
194
|
-
owner: "operator",
|
|
195
|
-
summary: `AgentRun ${run.id} for ${run.roleName} has no durable progress after ${progressAt}.`,
|
|
196
|
-
updatedAt: progressAt,
|
|
197
|
-
runId: run.id,
|
|
198
|
-
roleName: run.roleName
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
return items.sort((left, right) => (Date.parse(left.updatedAt) - Date.parse(right.updatedAt)
|
|
202
|
-
|| left.id.localeCompare(right.id)));
|
|
203
|
-
}
|
|
204
|
-
function collectBlockers(workItems, openInputRequests, attention) {
|
|
205
|
-
const blockers = [];
|
|
206
|
-
const workById = new Map(workItems.map((item) => [item.id, item]));
|
|
207
|
-
for (const item of workItems) {
|
|
208
|
-
if ((item.status === "open" && item.currentCandidateId !== undefined)) {
|
|
209
|
-
blockers.push({
|
|
210
|
-
kind: "work",
|
|
211
|
-
type: "work",
|
|
212
|
-
id: item.id,
|
|
213
|
-
status: item.status,
|
|
214
|
-
owner: "leader",
|
|
215
|
-
action: "accept-work-item",
|
|
216
|
-
summary: `Work Item ${item.id} is awaiting Leader acceptance.`
|
|
217
|
-
});
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
if (item.status !== "open")
|
|
221
|
-
continue;
|
|
222
|
-
const dependencies = item.dependsOn.filter((dependency) => (workById.get(dependency)?.status !== "accepted"));
|
|
223
|
-
if (dependencies.length === 0)
|
|
224
|
-
continue;
|
|
225
|
-
blockers.push({
|
|
226
|
-
kind: "work",
|
|
227
|
-
type: "work",
|
|
228
|
-
id: item.id,
|
|
229
|
-
status: item.status,
|
|
230
|
-
owner: item.assignee ?? "leader",
|
|
231
|
-
action: "unblock-work-item",
|
|
232
|
-
summary: `Work Item ${item.id} is waiting on ${dependencies.join(", ")}.`
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
for (const request of openInputRequests) {
|
|
236
|
-
blockers.push({
|
|
237
|
-
kind: "input",
|
|
238
|
-
type: "input",
|
|
239
|
-
id: request.id,
|
|
240
|
-
status: request.status,
|
|
241
|
-
owner: "user",
|
|
242
|
-
action: "answer-input",
|
|
243
|
-
summary: request.question,
|
|
244
|
-
blockedRefs: request.blockedRefs
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
for (const item of attention) {
|
|
248
|
-
blockers.push({
|
|
249
|
-
kind: "attention",
|
|
250
|
-
type: "attention",
|
|
251
|
-
id: item.id,
|
|
252
|
-
status: item.status,
|
|
253
|
-
owner: item.owner,
|
|
254
|
-
action: item.kind === "leader-recovery"
|
|
255
|
-
? "inspect-leader-recovery"
|
|
256
|
-
: "inspect-leader-stall",
|
|
257
|
-
summary: item.summary
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
return blockers;
|
|
261
|
-
}
|
|
262
|
-
function overviewNextAction(task, workItems, execution, action) {
|
|
263
|
-
if (task.status !== "active" && task.status !== "draft")
|
|
264
|
-
return null;
|
|
265
|
-
const primary = action.refs[0];
|
|
266
|
-
const workItem = action.refs
|
|
267
|
-
.filter(({ kind }) => kind === "work-item")
|
|
268
|
-
.map(({ id }) => workItems.find((item) => item.id === id))
|
|
269
|
-
.find((item) => item !== undefined);
|
|
270
|
-
const kind = primary?.kind === "input-request"
|
|
271
|
-
? "input"
|
|
272
|
-
: primary?.kind === "work-item"
|
|
273
|
-
? "work"
|
|
274
|
-
: action.kind.includes("attention") || action.kind.includes("inconsistency")
|
|
275
|
-
? "attention"
|
|
276
|
-
: "execution";
|
|
277
|
-
return {
|
|
278
|
-
action: action.kind,
|
|
279
|
-
owner: action.kind === "resolve-input"
|
|
280
|
-
? "user"
|
|
281
|
-
: workItem?.assignee ?? execution.owner,
|
|
282
|
-
kind,
|
|
283
|
-
...(primary === undefined ? {} : { id: primary.id }),
|
|
284
|
-
summary: action.reason
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
function countWorkItems(items) {
|
|
288
|
-
const counts = {
|
|
289
|
-
total: items.length,
|
|
290
|
-
open: 0,
|
|
291
|
-
accepted: 0,
|
|
292
|
-
retired: 0
|
|
293
|
-
};
|
|
294
|
-
for (const item of items)
|
|
295
|
-
counts[item.status] += 1;
|
|
296
|
-
return counts;
|
|
297
|
-
}
|
|
298
|
-
function leaderCell(task) {
|
|
299
|
-
const status = task.leader.roleStatus;
|
|
300
|
-
if (task.leader.summaryStatus === "missing")
|
|
301
|
-
return `${status} · missing summary`;
|
|
302
|
-
const values = [task.leader.summary, task.leader.currentFocus]
|
|
303
|
-
.filter((value) => value !== null && value.length > 0);
|
|
304
|
-
return values.length === 0
|
|
305
|
-
? `${status} · summary unavailable`
|
|
306
|
-
: compactText(`${status} · ${values.join(" · ")}`);
|
|
307
|
-
}
|
|
308
|
-
function workCell(counts) {
|
|
309
|
-
if (counts.total === 0)
|
|
310
|
-
return "none";
|
|
311
|
-
const details = Object.keys(counts)
|
|
312
|
-
.filter((status) => status !== "total" && counts[status] > 0)
|
|
313
|
-
.map((status) => `${status}:${counts[status]}`);
|
|
314
|
-
return `${counts.total} total${details.length === 0 ? "" : ` (${details.join(", ")})`}`;
|
|
315
|
-
}
|
|
316
|
-
function blockersCell(blockers) {
|
|
317
|
-
if (blockers.length === 0)
|
|
318
|
-
return "none";
|
|
319
|
-
return blockers.map((blocker) => `${blocker.kind}:${blocker.id}`).join(", ");
|
|
320
|
-
}
|
|
321
|
-
function nextCell(next) {
|
|
322
|
-
return next === null ? "—" : `${next.action} / ${next.owner}`;
|
|
323
|
-
}
|
|
324
|
-
function deliveryCell(delivery) {
|
|
325
|
-
if (delivery.status === "none")
|
|
326
|
-
return "none";
|
|
327
|
-
return `${delivery.status} · ${delivery.mergedProjectCount}/${delivery.codeProjectCount} merged`
|
|
328
|
-
+ (delivery.allMerged
|
|
329
|
-
? ` · ${delivery.verifiedProjectCount}/${delivery.codeProjectCount} verified`
|
|
330
|
-
: "");
|
|
331
|
-
}
|
|
332
|
-
function taskRemoteDeliveryCandidate(task) {
|
|
333
|
-
const projects = task.projectBindings.flatMap(({ projectId, currentCommit }) => (currentCommit === undefined ? [] : [{ projectId, commit: currentCommit }]));
|
|
334
|
-
return projects.length === task.projectBindings.length
|
|
335
|
-
? { projects }
|
|
336
|
-
: null;
|
|
337
|
-
}
|
|
338
|
-
function compactText(value) {
|
|
339
|
-
const oneLine = value.replace(/\s+/g, " ").trim();
|
|
340
|
-
return oneLine.length <= 240 ? oneLine : `${oneLine.slice(0, 237)}...`;
|
|
341
|
-
}
|
|
342
|
-
function renderVerboseDetails(tasks, timeZone) {
|
|
343
|
-
return [
|
|
344
|
-
"Task details",
|
|
345
|
-
...tasks.flatMap((task) => [
|
|
346
|
-
`${task.id}: ${task.title}`,
|
|
347
|
-
` Description: ${task.description ?? "—"}`,
|
|
348
|
-
` Current focus: ${task.currentFocus ?? "missing"}`,
|
|
349
|
-
` Leader summary: ${task.leaderSummary ?? "missing"}`,
|
|
350
|
-
` Summary updated by: ${task.summaryUpdatedBy ?? "unknown"}`,
|
|
351
|
-
` Summary updated at: ${task.summaryUpdatedAt === null
|
|
352
|
-
? "missing"
|
|
353
|
-
: formatTimestamp(task.summaryUpdatedAt, timeZone)}`,
|
|
354
|
-
` Execution: ${task.execution.status} (${task.execution.owner}); ${task.execution.summary}`,
|
|
355
|
-
` Remote delivery: ${deliveryCell(task.remoteDelivery)}; source=${task.remoteDelivery.source}${task.remoteDelivery.provisional ? " (provisional)" : ""}`,
|
|
356
|
-
` Monitoring: ${task.execution.monitoring}; attention: ${task.execution.attention.length}`,
|
|
357
|
-
` DAG: ${task.execution.observability.dag.nodes.length} nodes, ${task.execution.observability.dag.edges.length} edges; ready=${task.execution.observability.dag.readyIds.join(", ") || "none"}; blocked=${task.execution.observability.dag.blockedIds.join(", ") || "none"}`,
|
|
358
|
-
` Cost: tokens=${task.execution.observability.cost.tokens}${task.execution.observability.cost.tokensObservable ? "" : " (partial)"}; tools=${task.execution.observability.cost.toolCalls}${task.execution.observability.cost.toolCallsObservable ? "" : " (partial)"}; wall=${task.execution.observability.cost.wallClockSeconds}s; retries=${task.execution.observability.cost.retryCount}`,
|
|
359
|
-
` Context: snapshots=${task.execution.observability.context.snapshotCount}; bytes=${task.execution.observability.context.totalBytes ?? "partial"}; compression=unavailable`,
|
|
360
|
-
` Session tokens: ${task.execution.observability.sessionTokens.length === 0
|
|
361
|
-
? "unobserved"
|
|
362
|
-
: task.execution.observability.sessionTokens.map(({ roleName, metrics }) => {
|
|
363
|
-
const total = metrics.cumulativeTotal.status === "observed"
|
|
364
|
-
? metrics.cumulativeTotal.totalTokens
|
|
365
|
-
: "unobserved";
|
|
366
|
-
const maximum = metrics.maximumRequestInput.status === "observed"
|
|
367
|
-
? metrics.maximumRequestInput.inputTokens
|
|
368
|
-
: "unobserved";
|
|
369
|
-
return `${roleName}: total=${total}, max-request-input=${maximum}`;
|
|
370
|
-
}).join("; ")}`,
|
|
371
|
-
` Projects: ${task.projectBindings.length === 0
|
|
372
|
-
? "none"
|
|
373
|
-
: task.projectBindings.map(({ directory, projectId, baseRef }) => (`${directory} (${projectId} @ ${baseRef})`)).join(", ")}`
|
|
374
|
-
])
|
|
375
|
-
].join("\n");
|
|
376
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
import { usageError } from "../errors/cliError.js";
|
|
3
|
-
import { installCompletion, uninstallCompletion } from "./completionInstaller.js";
|
|
4
|
-
import { COMPLETION_SHELLS, activationBlock, activationIsAutomatic, currentCompletionShell, inspectCompletionStates, renderCompletionStateTable, shellQuote, suggestedCompletionInstallation } from "./completionState.js";
|
|
5
|
-
export async function runCompletionWizard(operation, store, env, identity, question, options = {}) {
|
|
6
|
-
const states = inspectCompletionStates(store.getConfig(), env, identity);
|
|
7
|
-
const current = currentCompletionShell(env);
|
|
8
|
-
let shell;
|
|
9
|
-
if (options.shell === undefined) {
|
|
10
|
-
const defaultSelection = options.defaultSelection ?? "current-shell";
|
|
11
|
-
const defaultHint = defaultSelection === "skip"
|
|
12
|
-
? " [skip]"
|
|
13
|
-
: current === undefined ? "" : ` [${current}]`;
|
|
14
|
-
const skipHint = defaultSelection === "skip" ? "" : " (or skip)";
|
|
15
|
-
const answer = await question(`${renderCompletionStateTable(states, options.width)}\n`
|
|
16
|
-
+ `Choose shell by number or name${defaultHint}${skipHint}: `);
|
|
17
|
-
const normalized = answer.trim().toLowerCase();
|
|
18
|
-
if (normalized === "skip" || (normalized.length === 0 && defaultSelection === "skip")) {
|
|
19
|
-
return `Completion ${operation} skipped.\n`;
|
|
20
|
-
}
|
|
21
|
-
shell = parseSelection(answer, current);
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
shell = options.shell;
|
|
25
|
-
}
|
|
26
|
-
const state = states.find((candidate) => candidate.shell === shell);
|
|
27
|
-
if (state === undefined)
|
|
28
|
-
throw usageError("Completion shell selection is invalid.");
|
|
29
|
-
if (operation === "uninstall") {
|
|
30
|
-
if (state.installation === undefined) {
|
|
31
|
-
return `Completion ${shell} is not installed.\n`;
|
|
32
|
-
}
|
|
33
|
-
const confirm = normalize(await question(`Remove managed ${shell} completion?\n`
|
|
34
|
-
+ `Script: ${state.installation.scriptPath}\n`
|
|
35
|
-
+ `Activation: ${state.installation.activationPath}\n`
|
|
36
|
-
+ "Remove now? [y/N]: "));
|
|
37
|
-
if (confirm !== "y" && confirm !== "yes") {
|
|
38
|
-
return `Completion ${shell} uninstall skipped.\n`;
|
|
39
|
-
}
|
|
40
|
-
uninstallCompletion(store, shell, identity);
|
|
41
|
-
return `Completion ${shell} uninstalled.\n`;
|
|
42
|
-
}
|
|
43
|
-
const suggested = state.installation
|
|
44
|
-
?? suggestedCompletionInstallation(shell, env, identity);
|
|
45
|
-
const automatic = activationIsAutomatic(shell, suggested, env, identity);
|
|
46
|
-
const decision = normalize(await question(`Selected: ${shell} (${state.action})\n`
|
|
47
|
-
+ `Script: ${suggested.scriptPath}\n`
|
|
48
|
-
+ `Activation: ${suggested.activationPath}`
|
|
49
|
-
+ `${automatic ? " (automatic)" : " (managed startup block)"}\n`
|
|
50
|
-
+ "Install using these paths? [Y/n/customize]: "));
|
|
51
|
-
if (decision === "n" || decision === "no") {
|
|
52
|
-
return `Completion ${shell} installation skipped.\n`;
|
|
53
|
-
}
|
|
54
|
-
let installation = suggested;
|
|
55
|
-
let customized = false;
|
|
56
|
-
if (decision === "customize") {
|
|
57
|
-
const scriptPath = resolve((await question(`Completion script path [${suggested.scriptPath}]: `)).trim()
|
|
58
|
-
|| suggested.scriptPath);
|
|
59
|
-
const activationPath = resolve((await question(`Activation file path [${suggested.activationPath}]: `)).trim()
|
|
60
|
-
|| suggested.activationPath);
|
|
61
|
-
installation = { scriptPath, activationPath };
|
|
62
|
-
customized = true;
|
|
63
|
-
}
|
|
64
|
-
else if (decision !== "" && decision !== "y" && decision !== "yes") {
|
|
65
|
-
throw usageError("Choose Y, n, or customize.");
|
|
66
|
-
}
|
|
67
|
-
const needsActivation = !activationIsAutomatic(shell, installation, env, identity);
|
|
68
|
-
let activate = false;
|
|
69
|
-
let activationReady = !needsActivation;
|
|
70
|
-
if (needsActivation) {
|
|
71
|
-
const activationAnswer = normalize(await question(`${activationBlock(shell, installation, identity)}\n`
|
|
72
|
-
+ `Update ${installation.activationPath} with the managed Yui block? [Y/n]: `));
|
|
73
|
-
if (activationAnswer !== ""
|
|
74
|
-
&& activationAnswer !== "y"
|
|
75
|
-
&& activationAnswer !== "yes"
|
|
76
|
-
&& activationAnswer !== "n"
|
|
77
|
-
&& activationAnswer !== "no") {
|
|
78
|
-
throw usageError("Choose Y or n.");
|
|
79
|
-
}
|
|
80
|
-
activate = activationAnswer === ""
|
|
81
|
-
|| activationAnswer === "y"
|
|
82
|
-
|| activationAnswer === "yes";
|
|
83
|
-
activationReady = activate || (!customized && state.status === "Installed");
|
|
84
|
-
}
|
|
85
|
-
installCompletion(store, shell, installation, env, identity, activate);
|
|
86
|
-
if (!activationReady) {
|
|
87
|
-
return `Completion ${shell} script installed; activation still required.\n`;
|
|
88
|
-
}
|
|
89
|
-
const result = `Completion ${shell} ${pastTense(state.action)}.\n`;
|
|
90
|
-
return needsActivation
|
|
91
|
-
? `${result}${activationGuidance(shell, installation, env, identity)}`
|
|
92
|
-
: result;
|
|
93
|
-
}
|
|
94
|
-
function activationGuidance(shell, installation, env, identity) {
|
|
95
|
-
const unchanged = "The current shell is unchanged.\n";
|
|
96
|
-
const defaultActivationPath = suggestedCompletionInstallation(shell, env, identity).activationPath;
|
|
97
|
-
if (installation.activationPath !== defaultActivationPath) {
|
|
98
|
-
return `${unchanged}From a ${shell} session, load the custom activation file: source ${shellQuote(installation.activationPath)}\n`;
|
|
99
|
-
}
|
|
100
|
-
return currentCompletionShell(env) === shell
|
|
101
|
-
? `${unchanged}Restart the current shell to activate completion: exec ${shell}\n`
|
|
102
|
-
: `${unchanged}Switch this terminal to ${shell} to activate completion: exec ${shell}\n`;
|
|
103
|
-
}
|
|
104
|
-
function parseSelection(value, current) {
|
|
105
|
-
const normalized = value.trim().toLowerCase();
|
|
106
|
-
if (normalized.length === 0 && current !== undefined)
|
|
107
|
-
return current;
|
|
108
|
-
if (/^[1-3]$/.test(normalized)) {
|
|
109
|
-
return COMPLETION_SHELLS[Number.parseInt(normalized, 10) - 1];
|
|
110
|
-
}
|
|
111
|
-
if (COMPLETION_SHELLS.includes(normalized)) {
|
|
112
|
-
return normalized;
|
|
113
|
-
}
|
|
114
|
-
throw usageError("Choose Bash, Zsh, or Fish by number or name.");
|
|
115
|
-
}
|
|
116
|
-
function pastTense(action) {
|
|
117
|
-
switch (action) {
|
|
118
|
-
case "Install": return "installed";
|
|
119
|
-
case "Refresh": return "refreshed";
|
|
120
|
-
case "Repair": return "repaired";
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
function normalize(value) {
|
|
124
|
-
return value?.trim().toLowerCase() ?? "";
|
|
125
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
export function buildRoleContext(context) {
|
|
2
|
-
return context.role.name === "leader"
|
|
3
|
-
? buildLeaderContext(context)
|
|
4
|
-
: buildWorkerContext(context);
|
|
5
|
-
}
|
|
6
|
-
export function buildLeaderContext(context) {
|
|
7
|
-
return renderDispatchContext("leader", context);
|
|
8
|
-
}
|
|
9
|
-
export function buildWorkerContext(context) {
|
|
10
|
-
return renderDispatchContext("worker", context);
|
|
11
|
-
}
|
|
12
|
-
const WORKER_RUN_COMPLETION_MARKER = "Yui Role AgentRun result requirement:";
|
|
13
|
-
const WORKER_RUN_COMPLETION_REQUIREMENT = [
|
|
14
|
-
WORKER_RUN_COMPLETION_MARKER,
|
|
15
|
-
"End the Provider turn with a truthful final report. Yui records that native turn result "
|
|
16
|
-
+ "for the current AgentRun automatically; no completion command is required.",
|
|
17
|
-
"If you cannot finally determine success, failure, completeness, or the correct "
|
|
18
|
-
+ "disposition, do not guess, silently stop, or hide uncertainty behind a success "
|
|
19
|
-
+ "summary. Label the final report uncertain, incomplete, "
|
|
20
|
-
+ "blocked, or requiring Leader judgment.",
|
|
21
|
-
"Report the most complete truthful evidence available and, when applicable: exact AgentRun, "
|
|
22
|
-
+ "WorkItem, and native Session identity; actions actually performed; changed paths "
|
|
23
|
-
+ "and commit/worktree state; checks actually run and their outcomes; provider, runtime, "
|
|
24
|
-
+ "or permission errors; the last confirmed lifecycle boundary; work not performed; "
|
|
25
|
-
+ "unresolved assumptions or decisions; residual risks; confidence; and bounded next options.",
|
|
26
|
-
"The Provider turn ending closes only this AgentRun. It does not imply Leader acceptance, "
|
|
27
|
-
+ "WorkItem completion, ChangeSet capture, Integration, or Task completion. Review AgentRuns "
|
|
28
|
-
+ "report findings, verification gaps, and limits; the Leader decides disposition."
|
|
29
|
-
].join("\n");
|
|
30
|
-
export function ensureWorkerRunCompletionRequirement(input) {
|
|
31
|
-
return input.endsWith(`\n\n${WORKER_RUN_COMPLETION_REQUIREMENT}`)
|
|
32
|
-
? input
|
|
33
|
-
: `${input}\n\n${WORKER_RUN_COMPLETION_REQUIREMENT}`;
|
|
34
|
-
}
|
|
35
|
-
function renderDispatchContext(kind, context) {
|
|
36
|
-
const profile = context.role;
|
|
37
|
-
const binding = profile.agentBindings[profile.activeAgentId];
|
|
38
|
-
const profileLines = [
|
|
39
|
-
`Task: ${context.taskId}`,
|
|
40
|
-
`Role: ${profile.name}`,
|
|
41
|
-
`Active Agent: ${profile.activeAgentId}`,
|
|
42
|
-
`Runtime: ${binding.adapterId}; model: ${binding.config.model ?? "CLI default"}; effort: ${binding.config.effort ?? "CLI default"}; permission: ${binding.config.permission.strategy}`,
|
|
43
|
-
profile.description === undefined ? null : `Description: ${profile.description}`,
|
|
44
|
-
...(profile.responsibilities ?? []).map((item) => `Responsibility: ${item}`),
|
|
45
|
-
...(profile.constraints ?? []).map((item) => `Constraint: ${item}`),
|
|
46
|
-
profile.expectedOutput === undefined ? null : `Expected output: ${profile.expectedOutput}`
|
|
47
|
-
].filter((line) => line !== null);
|
|
48
|
-
const workLines = kind === "worker"
|
|
49
|
-
? renderWorkerScope(context)
|
|
50
|
-
: [];
|
|
51
|
-
const rendered = [
|
|
52
|
-
`Follow the injected yui-${kind} Skill for this Yui dispatch.`,
|
|
53
|
-
renderContextLayers(context, kind),
|
|
54
|
-
profileLines.join("\n"),
|
|
55
|
-
workLines.length === 0 ? null : workLines.join("\n"),
|
|
56
|
-
"Yui dispatch:",
|
|
57
|
-
requireText(context.input, "dispatch input")
|
|
58
|
-
].filter((section) => section !== null && section.length > 0)
|
|
59
|
-
.join("\n\n");
|
|
60
|
-
return kind === "worker"
|
|
61
|
-
? ensureWorkerRunCompletionRequirement(rendered)
|
|
62
|
-
: rendered;
|
|
63
|
-
}
|
|
64
|
-
function renderContextLayers(context, kind) {
|
|
65
|
-
const projects = context.projectPolicy ?? [];
|
|
66
|
-
const policyLines = projects.length === 0
|
|
67
|
-
? ["- none (this Task is not Project-backed)"]
|
|
68
|
-
: projects.map(({ projectId, directory }) => {
|
|
69
|
-
const label = directory === undefined ? projectId : `${directory} (${projectId})`;
|
|
70
|
-
return `- ${label}: \`yui project show ${projectId}\`; then \`yui project knowledge list ${projectId}\` and show the relevant entries`;
|
|
71
|
-
});
|
|
72
|
-
return [
|
|
73
|
-
"Context layers:",
|
|
74
|
-
"- Yui Core: durable identity, lifecycle, access, workspace, and exact handoff safety.",
|
|
75
|
-
`- Generic ${kind} Skill: reusable role behavior and evidence discipline.`,
|
|
76
|
-
"- Project Policy: project-owned build, test, migration, release, and review rules; it is not a Yui Core default.",
|
|
77
|
-
...["Project Policy references:", ...policyLines],
|
|
78
|
-
"- Task Contract: the current Task brief, WorkItem objective, acceptance criteria, and dispatch input.",
|
|
79
|
-
"Do not import rules from another Project or Task, and do not infer Project Policy from repository files alone."
|
|
80
|
-
].join("\n");
|
|
81
|
-
}
|
|
82
|
-
function renderWorkerScope(context) {
|
|
83
|
-
if (context.workItem === undefined || context.workspace === undefined)
|
|
84
|
-
return [];
|
|
85
|
-
const writable = context.workspace.entries.filter(({ access }) => access === "write");
|
|
86
|
-
const contextOnly = context.workspace.entries.filter(({ access }) => access === "read");
|
|
87
|
-
const projectLines = (label, entries) => [
|
|
88
|
-
`${label}:`,
|
|
89
|
-
...(entries.length === 0
|
|
90
|
-
? ["- none"]
|
|
91
|
-
: entries.map(({ directory, projectId }) => `- ${directory} (${projectId})`))
|
|
92
|
-
];
|
|
93
|
-
return [
|
|
94
|
-
`WorkItem: ${context.workItem.id}`,
|
|
95
|
-
`Workspace root: ${context.workspace.root}`,
|
|
96
|
-
...projectLines("Writable Projects", writable),
|
|
97
|
-
...projectLines("Context-only Projects", contextOnly),
|
|
98
|
-
`Read the full Task state with \`yui task context ${context.taskId}\`.`,
|
|
99
|
-
`Read the current WorkItem scope with \`yui task work list ${context.taskId}\`.`,
|
|
100
|
-
"Modify only Writable Projects. If another Project must change, stop and ask "
|
|
101
|
-
+ "the Task Leader to expand this WorkItem scope before continuing."
|
|
102
|
-
];
|
|
103
|
-
}
|
|
104
|
-
function requireText(value, label) {
|
|
105
|
-
const normalized = value.trim();
|
|
106
|
-
if (normalized.length === 0 || normalized.includes("\0")) {
|
|
107
|
-
throw new Error(`${label} is required.`);
|
|
108
|
-
}
|
|
109
|
-
return normalized;
|
|
110
|
-
}
|