@zq-silk/yui 0.15.7 → 0.15.9
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 +194 -399
- package/ARCHITECTURE.zh-CN.md +151 -0
- package/README.md +306 -1131
- package/dist/agent/adapterCatalog.js +15 -2
- package/dist/agent/agent.js +23 -3
- package/dist/agent/argumentPolicy.js +7 -1
- package/dist/agent/connectionPlan.js +62 -0
- package/dist/agent/executionComponents.js +158 -0
- package/dist/agent/launchEnvironment.js +31 -3
- package/dist/agent/managedRuntimeEnvironment.js +3 -5
- package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
- package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
- package/dist/artifacts/artifactCapability.js +74 -0
- package/dist/artifacts/artifactCommitLock.js +249 -0
- package/dist/artifacts/artifactPaths.js +151 -0
- package/dist/artifacts/gitArtifactRef.js +146 -0
- package/dist/artifacts/managedGit.js +332 -0
- package/dist/artifacts/taskArtifactRepository.js +277 -0
- package/dist/brief/taskBrief.js +12 -0
- package/dist/cli/agentConfigurationPicker.js +13 -0
- package/dist/cli/commandCatalog.js +165 -74
- package/dist/cli/interactionCandidates.js +5 -5
- package/dist/cli/interactionPolicy.js +38 -8
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/managedDiagnostics.js +28 -0
- package/dist/cli/operatorWizard.js +1 -7
- package/dist/cli/roleOptionOrder.js +27 -0
- package/dist/cli/roleWizard.js +50 -14
- package/dist/cli/updateOrchestrator.js +1 -1
- package/dist/cli/updatePorts.js +3 -4
- package/dist/cli.js +245 -95
- package/dist/commands/agentCommands.js +72 -14
- package/dist/commands/capabilityCommands.js +9 -6
- package/dist/commands/configCommands.js +20 -20
- package/dist/commands/deliveryGuardPreflight.js +2 -2
- package/dist/commands/executionAuditCommands.js +24 -24
- package/dist/commands/globalRoleCommands.js +1 -1
- package/dist/commands/grantCommands.js +4 -4
- package/dist/commands/operatorCommands.js +34 -9
- package/dist/commands/projectCommands.js +4 -4
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/roleConfiguration.js +25 -5
- package/dist/commands/roleRuntimeGuard.js +4 -5
- package/dist/commands/sessionCommands.js +3 -7
- package/dist/commands/taskActivationCommands.js +281 -0
- package/dist/commands/taskActor.js +28 -49
- package/dist/commands/taskCommands.js +1461 -720
- package/dist/commands/taskContextCommand.js +39 -583
- package/dist/commands/taskExecutionCommands.js +32 -32
- package/dist/commands/taskInputCommands.js +40 -104
- package/dist/commands/taskIntegrationCommands.js +3 -2
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -8
- package/dist/commands/taskOverviewCommand.js +33 -45
- package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
- package/dist/commands/taskRoleRuntimeStatus.js +133 -102
- package/dist/commands/telemetryCommands.js +36 -38
- package/dist/config/configCatalog.js +4 -4
- package/dist/config/yuiConfig.js +8 -8
- package/dist/context/contextSnapshot.js +10 -10
- package/dist/context/dispatchContext.js +11 -11
- package/dist/context/roleSessionContext.js +6 -3
- package/dist/context/{turnContextPack.js → runContextPack.js} +158 -81
- package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
- package/dist/context/sessionBootstrapManifest.js +21 -2
- package/dist/context/sourceRunContext.js +30 -0
- package/dist/context/taskContext.js +481 -0
- package/dist/context/wakeNotification.js +27 -27
- package/dist/controller/agentRuntimeObserver.js +21 -24
- package/dist/controller/capabilityBridge.js +17 -6
- package/dist/controller/clientRuntime.js +65 -92
- package/dist/controller/controller.js +120 -188
- package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
- package/dist/controller/jobControl.js +54 -85
- package/dist/controller/resourceInventory.js +8 -27
- package/dist/controller/resourceInventoryLinux.js +12 -13
- package/dist/controller/runtime.js +529 -479
- package/dist/controller/runtimeEventInbox.js +55 -25
- package/dist/controller/runtimeEventProcessor.js +22 -31
- package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
- package/dist/controller/runtimeLaunchCoordinator.js +80 -426
- package/dist/controller/runtimeObservationHook.js +14 -18
- package/dist/controller/sessionNotify.js +16 -24
- package/dist/controller/sessionOwnerReconciliation.js +168 -50
- package/dist/controller/structuredProviderObservation.js +138 -99
- package/dist/coordination/workMailbox.js +3 -3
- package/dist/coordination/workMailboxQueue.js +36 -33
- package/dist/core/boundedRpc.js +8 -1
- package/dist/core/controllerClient.js +20 -1
- package/dist/core/controllerServer.js +4 -4
- package/dist/doctor/doctor.js +13 -2
- package/dist/domain/agentResultTransport.js +9 -9
- package/dist/execution/codexThreadNaming.js +2 -8
- package/dist/execution/executionHealth.js +51 -63
- package/dist/execution/reviewMainRun.js +137 -0
- package/dist/execution/workItemExecution.js +28 -29
- package/dist/execution/workItemExecutionProjection.js +99 -107
- package/dist/execution/workItemMainRun.js +141 -0
- package/dist/executor/agentAdapter.js +227 -20
- package/dist/executor/agentConfigurationCatalog.js +126 -4
- package/dist/executor/agentConfigurationProbe.js +162 -4
- package/dist/executor/agentExecutor.js +79 -78
- package/dist/executor/effectiveLaunch.js +105 -18
- package/dist/executor/executorRegistry.js +29 -44
- package/dist/executor/fileRoleLaunchPlanner.js +229 -154
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +6 -3
- package/dist/input/inputRequest.js +12 -10
- package/dist/integration/gitIntegrationService.js +4 -11
- package/dist/integration/integrationQueueService.js +4 -4
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/kernel/builtinCapabilities.js +255 -12
- package/dist/kernel/capabilityRegistry.js +64 -18
- package/dist/kernel/instanceHost.js +12 -1
- package/dist/kernel/kernelPorts.js +2 -2
- package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
- package/dist/lifecycle/exactRunTerminalization.js +449 -0
- package/dist/message/message.js +118 -6
- package/dist/message/messageContinuation.js +204 -0
- package/dist/observability/executionAudit.js +70 -72
- package/dist/observability/faultClassification.js +2 -2
- package/dist/observability/orchestrationMetrics.js +8 -8
- package/dist/operator/operatorSessionHistory.js +1 -7
- package/dist/output/agentConfigurationPresentation.js +8 -3
- package/dist/output/agentRunConfigurationPresentation.js +128 -0
- package/dist/output/rolePresentation.js +54 -3
- package/dist/plugins/pluginChild.js +104 -0
- package/dist/plugins/pluginIntent.js +26 -0
- package/dist/plugins/pluginInterpreter.js +43 -0
- package/dist/plugins/pluginPackage.js +101 -0
- package/dist/plugins/pluginProcess.js +112 -0
- package/dist/plugins/pluginService.js +388 -0
- package/dist/profile/agentProfile.js +1 -1
- package/dist/repository/gitWorkspace.js +26 -4
- package/dist/repository/project.js +19 -4
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +20 -27
- package/dist/repository/taskWorkspacePreparer.js +344 -83
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +3 -3
- package/dist/resources/projectResource.js +75 -0
- package/dist/resources/projectResourceService.js +343 -0
- package/dist/resources/resourceDiscovery.js +6 -6
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/resourceRegistrar.js +1 -1
- package/dist/resources/resourceTypes.js +1 -1
- package/dist/review/deltaRecheck.js +3 -3
- package/dist/review/reviewAcceptance.js +16 -16
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewRound.js +21 -20
- package/dist/review/reviewerAvailability.js +2 -2
- package/dist/role/role.js +51 -7
- package/dist/role/taskRoleUpdate.js +30 -0
- package/dist/runtime/acpProtocol.js +425 -0
- package/dist/runtime/acpSession.js +731 -0
- package/dist/runtime/acpSessionConfiguration.js +260 -0
- package/dist/runtime/agentDriver.js +30 -11
- package/dist/runtime/agentEndpoint.js +278 -0
- package/dist/runtime/agentEndpointIdentity.js +86 -0
- package/dist/runtime/agentEndpointOwnership.js +239 -0
- package/dist/runtime/agentError.js +2 -10
- package/dist/runtime/agentHost.js +565 -314
- package/dist/runtime/agentRunConfiguration.js +258 -0
- package/dist/runtime/builtinAgentDrivers.js +134 -18
- package/dist/runtime/builtinAgentErrorMappers.js +55 -3
- package/dist/runtime/builtinTranscriptUsage.js +1 -1
- package/dist/runtime/claude-process-owner +0 -0
- package/dist/runtime/codexAppServerRuntime.js +38 -30
- package/dist/runtime/codexInteractiveHost.js +41 -6
- package/dist/runtime/continuationManager.js +2 -6
- package/dist/runtime/executionEnvironment.js +30 -0
- package/dist/runtime/firstProgressAdvisory.js +11 -11
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/jsonLineChannel.js +109 -0
- package/dist/runtime/launchBroker.js +91 -16
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +10 -18
- package/dist/runtime/managedCaller.js +61 -17
- package/dist/runtime/nativeSessionControl.js +102 -0
- package/dist/runtime/ports.js +6 -21
- package/dist/runtime/processExitObservation.js +8 -7
- package/dist/runtime/promptEnvelope.js +17 -6
- package/dist/runtime/providerContinuation.js +3 -9
- package/dist/runtime/providerContinuationReconciliationService.js +4 -13
- package/dist/runtime/providerControl.js +2 -7
- package/dist/runtime/providerRuntimeIdentity.js +110 -222
- package/dist/runtime/providerRuntimeReconciler.js +5 -9
- package/dist/runtime/runtimeBinding.js +0 -1
- package/dist/runtime/runtimeContinuationProjection.js +4 -7
- package/dist/runtime/runtimeDeadlines.js +9 -0
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +29 -65
- package/dist/runtime/runtimeProjection.js +43 -51
- package/dist/runtime/runtimeSessionCandidate.js +1 -3
- package/dist/runtime/sessionLaunchRequest.js +3 -7
- package/dist/runtime/sessionOwnerIdentity.js +7 -54
- package/dist/runtime/sessionOwnerRegistry.js +22 -17
- package/dist/runtime/sessionReconciliation.js +4 -8
- package/dist/runtime/sessionTerminationGuard.js +70 -259
- package/dist/runtime/sessionTokenMetrics.js +5 -16
- package/dist/runtime/structuredProviderHost.js +237 -117
- package/dist/runtime/taskRuntimeIsolation.js +39 -122
- package/dist/runtime/tmuxAdapters.js +39 -86
- package/dist/scheduler/activeRoleRunDelivery.js +354 -0
- package/dist/scheduler/leaderWakeupProcessor.js +75 -266
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +80 -9
- package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
- package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
- package/dist/scheduler/taskExecutionProjection.js +120 -124
- package/dist/scheduler/taskObservabilityProjection.js +29 -29
- package/dist/scheduler/taskWake.js +11 -4
- package/dist/scheduler/wakeReason.js +9 -1
- package/dist/setup/setupCommand.js +3 -7
- package/dist/storage/migrations/agentRunContract.js +159 -0
- package/dist/storage/migrations/artifactsToGit.js +338 -0
- package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
- package/dist/storage/migrations/submitIntent.js +126 -0
- package/dist/storage/sqliteSchema.js +467 -7
- package/dist/storage/sqliteStore.js +355 -220
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +10 -5
- package/dist/storage/taskStore.js +13 -11
- package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
- package/dist/surface/surfaceContributions.js +102 -0
- package/dist/task/completionReadiness.js +32 -6
- package/dist/task/deliveryGuard.js +16 -16
- package/dist/task/draftPlan.js +72 -12
- package/dist/task/nextAction.js +144 -128
- package/dist/task/remoteDelivery.js +6 -6
- package/dist/task/task.js +184 -18
- package/dist/task/taskActivation.js +327 -0
- package/dist/task/taskActivationService.js +408 -0
- package/dist/task/taskRecordReference.js +5 -4
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/task/taskSubmission.js +236 -0
- package/dist/telemetry/sqliteTelemetryStore.js +55 -68
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +2 -2
- package/dist/web/assets/assetManifest.js +2 -0
- package/dist/web/assets/client/app.js +121 -20
- package/dist/web/assets/client/components.js +87 -54
- package/dist/web/assets/client/i18n.js +83 -41
- package/dist/web/assets/client/markdown.js +1 -1
- package/dist/web/assets/client/taskSurface.js +442 -0
- package/dist/web/assets/client/view.js +49 -44
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +22 -4
- package/dist/web/controllerWeb.js +60 -0
- package/dist/web/webMutation.js +28 -0
- package/dist/web/webServer.js +133 -8
- package/dist/web/webSnapshot.js +81 -74
- package/dist/web/webTaskSurface.js +64 -0
- package/dist/workItem/dependencyGate.js +1 -1
- package/dist/workItem/workItem.js +84 -48
- package/dist/workspace/workItemChangeSetManager.js +16 -9
- package/docs/agent-result-consumption.md +96 -0
- package/docs/agent-result-consumption.zh-CN.md +81 -0
- package/docs/agent-runtime-drivers.md +93 -0
- package/docs/agent-runtime-drivers.zh-CN.md +77 -0
- package/docs/architecture/README.md +50 -0
- package/docs/architecture/README.zh-CN.md +43 -0
- package/docs/architecture/capabilities-and-resources.md +118 -0
- package/docs/architecture/capabilities-and-resources.zh-CN.md +83 -0
- package/docs/managed-turn-and-session-runtime.md +224 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +180 -0
- package/docs/observability/README.md +83 -0
- package/docs/observability/README.zh-CN.md +71 -0
- package/docs/plugin-sdk.md +393 -0
- package/docs/plugin-sdk.zh-CN.md +293 -0
- package/docs/provider-runtime.md +165 -0
- package/docs/provider-runtime.zh-CN.md +132 -0
- package/docs/release-workflow.md +305 -0
- package/docs/release-workflow.zh-CN.md +237 -0
- package/docs/roles-and-configuration.md +115 -0
- package/docs/roles-and-configuration.zh-CN.md +96 -0
- package/docs/sqlite-control-plane-design.md +78 -0
- package/docs/sqlite-control-plane-design.zh-CN.md +62 -0
- package/docs/task-dag-semantics.md +80 -0
- package/docs/task-dag-semantics.zh-CN.md +59 -0
- package/docs/task-delivery.md +105 -0
- package/docs/task-delivery.zh-CN.md +82 -0
- package/docs/task-local-identity.md +8 -6
- package/docs/task-local-identity.zh-CN.md +58 -0
- package/docs/testing/verification-levels.md +88 -0
- package/docs/testing/verification-levels.zh-CN.md +69 -0
- package/i18n/README.zh-CN.md +270 -722
- package/package.json +3 -2
- package/skills/yui-leader/SKILL.md +88 -304
- package/skills/yui-leader/references/execution.md +303 -0
- package/skills/yui-leader/references/integration.md +39 -0
- package/skills/yui-leader/references/planning.md +109 -0
- package/skills/yui-leader/references/replicated-execution.md +42 -0
- package/skills/yui-leader/references/task-plugins.md +37 -0
- package/skills/yui-operator/SKILL.md +46 -62
- package/skills/yui-reviewer/SKILL.md +35 -36
- package/skills/yui-runtime/SKILL.md +88 -24
- package/skills/yui-runtime/references/publication.md +22 -0
- package/skills/yui-runtime/references/recovery.md +64 -0
- package/skills/yui-worker/SKILL.md +37 -39
- package/dist/cli/roleOptionCatalog.js +0 -68
- package/dist/context/sourceTurnContext.js +0 -30
- package/dist/execution/reviewMainTurn.js +0 -161
- package/dist/execution/workItemMainTurn.js +0 -164
- package/dist/lifecycle/exactTurnTerminalization.js +0 -407
- package/dist/runtime/preallocatedNativeSession.js +0 -13
- package/dist/runtime/runtimeStopReceipt.js +0 -42
- package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
|
+
import { createRun, withRunContextSnapshot } from "../agentRun/agentRun.js";
|
|
3
|
+
import { createRunInput } from "../context/runInputContract.js";
|
|
4
|
+
import { contextContentDigest, contextSnapshotRef, createContextSnapshot } from "../context/contextSnapshot.js";
|
|
5
|
+
import { roleSessionMayContinue } from "../executor/effectiveLaunch.js";
|
|
6
|
+
import { enqueueRoleRunDispatch } from "../coordination/workMailboxQueue.js";
|
|
7
|
+
import { createTaskEvent } from "../event/taskEvent.js";
|
|
8
|
+
import { validateExactRunReviewRound } from "../lifecycle/exactRunTerminalization.js";
|
|
9
|
+
import { sourceRunContextValue } from "../context/sourceRunContext.js";
|
|
10
|
+
import { requireManagedTaskCaller } from "../runtime/managedCaller.js";
|
|
11
|
+
export function resolveMessageRecipient(store, taskId, roleName, scope) {
|
|
12
|
+
if (scope.reviewRoundId !== undefined) {
|
|
13
|
+
const round = store.getReviewRound(taskId, scope.reviewRoundId);
|
|
14
|
+
if (round === null)
|
|
15
|
+
throw new Error("ReviewRound is unavailable in this Task.");
|
|
16
|
+
if (scope.workItemId !== undefined && scope.workItemId !== round.workItemId)
|
|
17
|
+
throw new Error("ReviewRound WorkItem scope mismatch.");
|
|
18
|
+
scope = { reviewRoundId: scope.reviewRoundId, ...(round.workItemId === undefined ? {} : { workItemId: round.workItemId }) };
|
|
19
|
+
}
|
|
20
|
+
if (scope.workItemId === undefined && scope.reviewRoundId === undefined) {
|
|
21
|
+
throw new Error("Recipient requires --work-item or --review-round; Message does not establish an Assignment.");
|
|
22
|
+
}
|
|
23
|
+
const previous = store.listRuns(taskId).filter((run) => run.roleName === roleName && run.workItemId === scope.workItemId
|
|
24
|
+
&& run.reviewRoundId === scope.reviewRoundId).at(-1);
|
|
25
|
+
if (previous === undefined)
|
|
26
|
+
throw new Error("No existing Dispatch owns this Role and work scope.");
|
|
27
|
+
return { roleName, ownerRunId: previous.id, ...scope };
|
|
28
|
+
}
|
|
29
|
+
/** Bounded diagnosis, not automatic ownership repair. */
|
|
30
|
+
export function messageContinuationBlocker(store, message) {
|
|
31
|
+
const target = message.recipient;
|
|
32
|
+
if (target?.ownerRunId === undefined)
|
|
33
|
+
return "recipient-assignment-missing";
|
|
34
|
+
const task = store.getTask(message.taskId);
|
|
35
|
+
if (task?.status !== "active")
|
|
36
|
+
return `task-${task?.status ?? "missing"}`;
|
|
37
|
+
if (task.executionGate.state !== "enabled")
|
|
38
|
+
return "execution-disabled";
|
|
39
|
+
const owner = store.getRun(message.taskId, target.ownerRunId);
|
|
40
|
+
if (owner === null || owner.roleName !== target.roleName || owner.workItemId !== target.workItemId
|
|
41
|
+
|| owner.reviewRoundId !== target.reviewRoundId)
|
|
42
|
+
return "owner-assignment-mismatch";
|
|
43
|
+
if (owner.result?.failureReason === "delivery-unknown")
|
|
44
|
+
return "owner-acceptance-unknown";
|
|
45
|
+
if (owner.executionGroupId !== undefined || owner.sourceExecutionGroupId !== undefined) {
|
|
46
|
+
return "replicated-assignment-requires-explicit-dispatch";
|
|
47
|
+
}
|
|
48
|
+
if (target.workItemId !== undefined) {
|
|
49
|
+
const work = store.getWorkItem(message.taskId, target.workItemId);
|
|
50
|
+
if (work?.status !== "open")
|
|
51
|
+
return `work-item-${work?.status ?? "missing"}`;
|
|
52
|
+
if (target.reviewRoundId === undefined && work.assignee !== target.roleName)
|
|
53
|
+
return "owner-changed";
|
|
54
|
+
if (target.reviewRoundId === undefined && !isDeepStrictEqual([...work.writeProjectIds].sort(), [...owner.effective.writeProjectIds].sort()))
|
|
55
|
+
return "assignment-scope-changed";
|
|
56
|
+
if (target.reviewRoundId === undefined && owner.workspace !== undefined) {
|
|
57
|
+
const workspace = target.roleName === "leader"
|
|
58
|
+
? store.getTaskWorkspace(message.taskId) : store.getWorkItemWorkspace(message.taskId, target.workItemId);
|
|
59
|
+
const identity = (entries) => entries.map((entry) => ({
|
|
60
|
+
projectId: entry.projectId, path: entry.path, access: entry.access, branch: entry.branch
|
|
61
|
+
}));
|
|
62
|
+
if (workspace?.root !== owner.workspace.root
|
|
63
|
+
|| !isDeepStrictEqual(identity(workspace.entries), identity(owner.workspace.entries))) {
|
|
64
|
+
return "assignment-workspace-changed";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const ownershipAt = message.handovers?.at(-1)?.at ?? message.createdAt;
|
|
68
|
+
if (target.reviewRoundId === undefined && store.listEvents(message.taskId).some((event) => event.type === "work.edited" && event.payload.workItemId === target.workItemId
|
|
69
|
+
&& event.payload.fields?.split(",").includes("assignee")
|
|
70
|
+
&& event.createdAt > ownershipAt && event.payload.previous !== event.payload.current))
|
|
71
|
+
return "owner-changed";
|
|
72
|
+
}
|
|
73
|
+
const latest = store.listRuns(message.taskId).filter((run) => run.workItemId === owner.workItemId && run.reviewRoundId === owner.reviewRoundId
|
|
74
|
+
&& run.roleName === owner.roleName).at(-1);
|
|
75
|
+
if (latest !== undefined && latest.id !== owner.id
|
|
76
|
+
&& latest.inputs[0]?.input.source.channel !== "message-continuation")
|
|
77
|
+
return "assignment-changed";
|
|
78
|
+
if (target.reviewRoundId !== undefined) {
|
|
79
|
+
const round = store.getReviewRound(message.taskId, target.reviewRoundId);
|
|
80
|
+
if (round === null)
|
|
81
|
+
return "review-round-missing";
|
|
82
|
+
if ((round.scope ?? "work-item") === "task") {
|
|
83
|
+
if (round.taskCandidate?.projects.some((project) => task.projectBindings.find((binding) => binding.projectId === project.projectId)?.currentCommit !== project.commit)) {
|
|
84
|
+
return "review-candidate-stale";
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const item = store.getWorkItem(message.taskId, round.workItemId);
|
|
89
|
+
if (item?.candidates.at(-1)?.id !== round.candidateId)
|
|
90
|
+
return "review-candidate-stale";
|
|
91
|
+
}
|
|
92
|
+
const validation = validateExactRunReviewRound(store, latest ?? owner, { allowTerminal: true });
|
|
93
|
+
if (validation.disposition !== "applied")
|
|
94
|
+
return validation.reason ?? "review-candidate-stale";
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
/** Called in the Controller's ordinary reconciliation transaction. Messages
|
|
99
|
+
* remain the pending authority; Mailbox is only the existing scheduling hint.
|
|
100
|
+
* Reserving inputs and creating the next Run is one atomic effect. */
|
|
101
|
+
export function prepareMessageContinuations(store, taskId, now, roleName) {
|
|
102
|
+
const pending = store.listMessages(taskId).filter((message) => message.recipient?.roleName === roleName && message.recipient.ownerRunId !== undefined
|
|
103
|
+
&& message.continuation?.runId === undefined);
|
|
104
|
+
for (const message of pending) {
|
|
105
|
+
const recipient = message.recipient;
|
|
106
|
+
const blocker = messageContinuationBlocker(store, message);
|
|
107
|
+
if (blocker !== undefined) {
|
|
108
|
+
markNotDelivered(store, message, blocker);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (store.getActiveRun(taskId, recipient.roleName) !== null)
|
|
112
|
+
continue;
|
|
113
|
+
const owner = store.getRun(taskId, recipient.ownerRunId);
|
|
114
|
+
const sessions = store.getTaskRoleSessionSet(taskId, recipient.roleName);
|
|
115
|
+
const session = sessions?.sessions[owner.effective.agentId];
|
|
116
|
+
const provider = sessions?.providerBinding;
|
|
117
|
+
if (provider?.authority.owner === "human" || provider?.authority.owner === "unknown"
|
|
118
|
+
|| (provider?.run !== null && provider?.run !== undefined
|
|
119
|
+
&& ["submitting", "accepted", "delivery-unknown"].includes(provider.run.status)))
|
|
120
|
+
continue;
|
|
121
|
+
if (session?.status !== "active" || sessions?.activeAgentId !== owner.effective.agentId
|
|
122
|
+
|| store.getRole(taskId, recipient.roleName)?.activeAgentId !== owner.effective.agentId
|
|
123
|
+
|| !roleSessionMayContinue(session.effective, owner.effective)) {
|
|
124
|
+
markNotDelivered(store, message, "compatible-session-unavailable");
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
// Reuse the same current-Session authority gate as Task-local actions.
|
|
128
|
+
// Matching Agent/effective flags alone do not undo explicit revocation.
|
|
129
|
+
requireManagedTaskCaller(store, {
|
|
130
|
+
YUI_SESSION_SCOPE: "task", YUI_TASK_ID: taskId, YUI_ROLE: recipient.roleName,
|
|
131
|
+
YUI_NATIVE_SESSION_ID: session.nativeSessionId, YUI_WORKSPACE: owner.effective.workspace.root
|
|
132
|
+
});
|
|
133
|
+
const originalNativeSessionId = store.listEvents(taskId).filter((event) => event.type === "run.session-prepared"
|
|
134
|
+
&& event.payload.runId === owner.id && event.payload.roleName === owner.roleName)
|
|
135
|
+
.at(-1)?.payload.nativeSessionId ?? owner.result?.provider?.conversationId;
|
|
136
|
+
if (originalNativeSessionId === undefined || originalNativeSessionId !== session.nativeSessionId) {
|
|
137
|
+
markNotDelivered(store, message, originalNativeSessionId === undefined
|
|
138
|
+
? "owner-session-unobserved" : "owner-session-changed");
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const batch = pending.filter((entry) => isDeepStrictEqual(entry.recipient, recipient)
|
|
142
|
+
&& messageContinuationBlocker(store, entry) === undefined).slice(0, 16);
|
|
143
|
+
const previous = store.listRuns(taskId).filter((run) => run.roleName === owner.roleName
|
|
144
|
+
&& run.workItemId === owner.workItemId && run.reviewRoundId === owner.reviewRoundId).at(-1);
|
|
145
|
+
const baselineRef = previous.inputs[0]?.input.contextSnapshotRef;
|
|
146
|
+
const baseline = baselineRef === undefined ? null : store.getContextSnapshot(taskId, baselineRef.id);
|
|
147
|
+
if (baseline === null || baseline.digest !== baselineRef.digest) {
|
|
148
|
+
markNotDelivered(store, message, "assignment-context-unavailable");
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const runId = store.nextRunId(taskId);
|
|
152
|
+
const round = owner.reviewRoundId === undefined ? null : store.getReviewRound(taskId, owner.reviewRoundId);
|
|
153
|
+
const continuingRound = round === null ? null : (() => {
|
|
154
|
+
const { endedAt: _endedAt, failure: _failure, ...current } = round;
|
|
155
|
+
return { ...current, status: "running", reviewerRunId: runId };
|
|
156
|
+
})();
|
|
157
|
+
const priorMessages = baseline.resources.filter((entry) => entry.ref.store === "task-message").slice(-16);
|
|
158
|
+
const source = sourceRunContextValue(previous);
|
|
159
|
+
const resources = [...baseline.resources.filter((entry) => entry.ref.store !== "task-message" && entry.ref.store !== "source-run"
|
|
160
|
+
&& !(continuingRound !== null && entry.ref.store === "review-round" && entry.ref.refId === continuingRound.id)),
|
|
161
|
+
...(continuingRound === null ? [] : [{ ref: { layer: "L3", store: "review-round",
|
|
162
|
+
refId: continuingRound.id, revision: now.toISOString(), digest: contextContentDigest(continuingRound),
|
|
163
|
+
summary: `ReviewRound ${continuingRound.id}` }, value: continuingRound }]),
|
|
164
|
+
...priorMessages,
|
|
165
|
+
{ ref: { layer: "L4", store: "source-run", refId: previous.id,
|
|
166
|
+
revision: previous.updatedAt, digest: contextContentDigest(source), summary: `Previous result ${previous.id}` }, value: source },
|
|
167
|
+
...batch.map((entry) => ({
|
|
168
|
+
ref: { layer: "L4", store: "task-message", refId: entry.id,
|
|
169
|
+
revision: entry.createdAt, digest: contextContentDigest(entry), summary: `Message ${entry.id}` },
|
|
170
|
+
value: entry
|
|
171
|
+
}))];
|
|
172
|
+
const latestSnapshot = store.listContextSnapshots(taskId).filter((entry) => entry.scope === baseline.scope && entry.scopeRef === baseline.scopeRef).at(-1);
|
|
173
|
+
const snapshot = createContextSnapshot({
|
|
174
|
+
...baseline, id: store.nextContextSnapshotId(taskId),
|
|
175
|
+
sequence: (latestSnapshot?.sequence ?? baseline.sequence) + 1,
|
|
176
|
+
parentRef: contextSnapshotRef(baseline), frozenAt: now, frozenBy: "controller",
|
|
177
|
+
resources, refs: resources.map(({ ref }) => ref)
|
|
178
|
+
});
|
|
179
|
+
store.saveContextSnapshot(snapshot);
|
|
180
|
+
const run = withRunContextSnapshot(createRun(runId, taskId, recipient.roleName, "resume", createRunInput({ source: { type: "yui", channel: "message-continuation" },
|
|
181
|
+
directive: `Continue the same Assignment in its existing workspace. Read Messages ${batch.map((m) => m.id).join(", ")} from this exact Context. Message receipt is not implementation or acceptance.`,
|
|
182
|
+
deltaRefIds: batch.map((entry) => entry.id) }), now, copyAssignment(owner)), contextSnapshotRef(snapshot), batch.map((entry) => entry.id));
|
|
183
|
+
store.saveRun(run);
|
|
184
|
+
store.saveActiveRun(run);
|
|
185
|
+
if (continuingRound !== null)
|
|
186
|
+
store.saveReviewRound(taskId, continuingRound);
|
|
187
|
+
for (const entry of batch)
|
|
188
|
+
store.updateMessage(taskId, { ...entry, continuation: { runId } });
|
|
189
|
+
enqueueRoleRunDispatch(store, { taskId, roleName: run.roleName, runId,
|
|
190
|
+
reason: "message-continuation", occurredAt: now });
|
|
191
|
+
store.saveEvent(taskId, createTaskEvent(store.nextEventId(taskId), taskId, "message.continuation", { runId, roleName: run.roleName, messageIds: batch.map((entry) => entry.id).join(",") }, now));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function copyAssignment(run) {
|
|
195
|
+
return { purpose: run.purpose, effective: run.effective,
|
|
196
|
+
...(run.workItemId === undefined ? {} : { workItemId: run.workItemId }),
|
|
197
|
+
...(run.reviewRoundId === undefined ? {} : { reviewRoundId: run.reviewRoundId }),
|
|
198
|
+
...(run.workspace === undefined ? {} : { workspace: run.workspace }) };
|
|
199
|
+
}
|
|
200
|
+
function markNotDelivered(store, message, reason) {
|
|
201
|
+
if (message.continuation?.notDeliveredReason === reason)
|
|
202
|
+
return;
|
|
203
|
+
store.updateMessage(message.taskId, { ...message, continuation: { notDeliveredReason: reason } });
|
|
204
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Read-only execution audit aggregator (Issue 11 §3).
|
|
3
3
|
*
|
|
4
4
|
* The audit answers "what happened in this Home" from durable records alone:
|
|
5
|
-
*
|
|
5
|
+
* AgentRuns/failures/durations, wake reasons, Runtime count, Review execution
|
|
6
6
|
* vs semantic failures, Integration failure classes and gate reuse, telemetry
|
|
7
7
|
* volume, and the longest/stale executions. It never writes Task state, never
|
|
8
8
|
* wakes a Leader, and never takes the storage write lock — it only calls the
|
|
@@ -15,7 +15,7 @@ import { join } from "node:path";
|
|
|
15
15
|
import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
|
|
16
16
|
import { resolveTaskStoreBackendForHome } from "../storage/sqliteStore.js";
|
|
17
17
|
import { runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
|
|
18
|
-
import {
|
|
18
|
+
import { classifyRunFailure, classifyIntegrationAttempt, classifyReviewRound, countFaultClasses } from "./faultClassification.js";
|
|
19
19
|
import { RUNTIME_LAUNCH_KINDS, RUNTIME_LAUNCH_PHASES } from "../runtime/launchDiagnostics.js";
|
|
20
20
|
import { UNSUPPORTED } from "./runtimeIdentity.js";
|
|
21
21
|
import { projectTaskOrchestration } from "./orchestrationMetrics.js";
|
|
@@ -86,10 +86,10 @@ function roleBucket(roleName) {
|
|
|
86
86
|
}
|
|
87
87
|
return "other";
|
|
88
88
|
}
|
|
89
|
-
function durationMs(
|
|
90
|
-
if (
|
|
89
|
+
function durationMs(run) {
|
|
90
|
+
if (run.result === undefined)
|
|
91
91
|
return 0;
|
|
92
|
-
return Math.max(0, Date.parse(
|
|
92
|
+
return Math.max(0, Date.parse(run.result.completedAt) - Date.parse(run.createdAt));
|
|
93
93
|
}
|
|
94
94
|
function emptyLaunchFailureCounts() {
|
|
95
95
|
const counts = {
|
|
@@ -116,35 +116,35 @@ function addLaunchFailureCounts(counts, summary) {
|
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
118
118
|
* Issue 09: classify a terminal Session (stopped/broken) by its relationship
|
|
119
|
-
* to the last
|
|
120
|
-
* that stops after its
|
|
119
|
+
* to the last AgentRun it carried. AgentRuns and Sessions are separate axes: a Session
|
|
120
|
+
* that stops after its AgentRun completed is a post-completion stop, not a AgentRun
|
|
121
121
|
* failure. Correlation is by Role + Agent + Adapter (the durable identity a
|
|
122
|
-
*
|
|
122
|
+
* AgentRun and its Session share) and the Session's terminal update timestamp.
|
|
123
123
|
*/
|
|
124
|
-
function
|
|
124
|
+
function classifyTerminalSessionRunRelation(runs, roleName, session, counts) {
|
|
125
125
|
const terminalAt = Date.parse(session.updatedAt);
|
|
126
|
-
const carried =
|
|
127
|
-
.filter((
|
|
128
|
-
&&
|
|
129
|
-
&&
|
|
130
|
-
&& Date.parse(
|
|
126
|
+
const carried = runs
|
|
127
|
+
.filter((run) => (run.roleName === roleName
|
|
128
|
+
&& run.effective.agentId === session.agentId
|
|
129
|
+
&& run.effective.adapterId === session.adapterId
|
|
130
|
+
&& Date.parse(run.createdAt) <= terminalAt))
|
|
131
131
|
.sort((left, right) => Date.parse(right.createdAt) - Date.parse(left.createdAt));
|
|
132
|
-
const
|
|
133
|
-
if (
|
|
134
|
-
counts.
|
|
132
|
+
const lastRun = carried[0];
|
|
133
|
+
if (lastRun === undefined) {
|
|
134
|
+
counts.noRun += 1;
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
-
if (
|
|
138
|
-
&&
|
|
139
|
-
&& Date.parse(
|
|
140
|
-
counts.
|
|
137
|
+
if (lastRun.status === "completed"
|
|
138
|
+
&& lastRun.result !== undefined
|
|
139
|
+
&& Date.parse(lastRun.result.completedAt) <= terminalAt) {
|
|
140
|
+
counts.postRunCompleted += 1;
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
|
-
if (
|
|
144
|
-
counts.
|
|
143
|
+
if (lastRun.status === "failed") {
|
|
144
|
+
counts.runFailed += 1;
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
counts.
|
|
147
|
+
counts.activeRun += 1;
|
|
148
148
|
}
|
|
149
149
|
function ok(data) {
|
|
150
150
|
return { status: "ok", data };
|
|
@@ -182,7 +182,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
182
182
|
homeIdentity: UNSUPPORTED,
|
|
183
183
|
scope,
|
|
184
184
|
tasks: section,
|
|
185
|
-
|
|
185
|
+
runs: section,
|
|
186
186
|
wakes: section,
|
|
187
187
|
sessions: section,
|
|
188
188
|
reviews: section,
|
|
@@ -228,7 +228,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
228
228
|
return failed(error);
|
|
229
229
|
}
|
|
230
230
|
})();
|
|
231
|
-
const
|
|
231
|
+
const runs = (() => {
|
|
232
232
|
try {
|
|
233
233
|
let total = 0;
|
|
234
234
|
let active = 0;
|
|
@@ -241,30 +241,30 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
241
241
|
const failures = [];
|
|
242
242
|
const launchFailures = emptyLaunchFailureCounts();
|
|
243
243
|
for (const taskId of taskIds) {
|
|
244
|
-
for (const
|
|
245
|
-
if (!inWindow(
|
|
244
|
+
for (const run of store.listRuns(taskId)) {
|
|
245
|
+
if (!inWindow(run.createdAt, options))
|
|
246
246
|
continue;
|
|
247
247
|
total += 1;
|
|
248
|
-
byRole[roleBucket(
|
|
249
|
-
if (
|
|
248
|
+
byRole[roleBucket(run.roleName)] += 1;
|
|
249
|
+
if (run.purpose === "review")
|
|
250
250
|
byPurpose.review += 1;
|
|
251
251
|
else
|
|
252
252
|
byPurpose.execution += 1;
|
|
253
|
-
const duration = durationMs(
|
|
254
|
-
if (
|
|
253
|
+
const duration = durationMs(run);
|
|
254
|
+
if (run.status === "active") {
|
|
255
255
|
active += 1;
|
|
256
|
-
cumulativeDurationMs += Math.max(0, Date.now() - Date.parse(
|
|
256
|
+
cumulativeDurationMs += Math.max(0, Date.now() - Date.parse(run.createdAt));
|
|
257
257
|
}
|
|
258
|
-
else if (
|
|
258
|
+
else if (run.status === "completed") {
|
|
259
259
|
completed += 1;
|
|
260
260
|
cumulativeDurationMs += duration;
|
|
261
261
|
}
|
|
262
|
-
else if (
|
|
262
|
+
else if (run.status === "failed") {
|
|
263
263
|
failedCount += 1;
|
|
264
264
|
failedDurationMs += duration;
|
|
265
265
|
cumulativeDurationMs += duration;
|
|
266
|
-
addLaunchFailureCounts(launchFailures,
|
|
267
|
-
failures.push(
|
|
266
|
+
addLaunchFailureCounts(launchFailures, run.result?.diagnostic);
|
|
267
|
+
failures.push(classifyRunFailure(run));
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
}
|
|
@@ -288,18 +288,18 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
288
288
|
})();
|
|
289
289
|
const wakes = (() => {
|
|
290
290
|
try {
|
|
291
|
-
let
|
|
291
|
+
let leaderRuns = 0;
|
|
292
292
|
let withWakeReasons = 0;
|
|
293
293
|
let suppressedWakes = 0;
|
|
294
294
|
const byReason = new Map();
|
|
295
295
|
for (const taskId of taskIds) {
|
|
296
|
-
for (const
|
|
297
|
-
if (
|
|
296
|
+
for (const run of store.listRuns(taskId)) {
|
|
297
|
+
if (run.roleName !== "leader")
|
|
298
298
|
continue;
|
|
299
|
-
if (!inWindow(
|
|
299
|
+
if (!inWindow(run.createdAt, options))
|
|
300
300
|
continue;
|
|
301
|
-
|
|
302
|
-
const match = WAKE_REASON_PATTERN.exec(
|
|
301
|
+
leaderRuns += 1;
|
|
302
|
+
const match = WAKE_REASON_PATTERN.exec(run.inputs[0].input.directive ?? "");
|
|
303
303
|
if (match === null)
|
|
304
304
|
continue;
|
|
305
305
|
withWakeReasons += 1;
|
|
@@ -317,12 +317,12 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
return ok({
|
|
320
|
-
|
|
320
|
+
leaderRuns,
|
|
321
321
|
withWakeReasons,
|
|
322
322
|
byReason: Object.fromEntries([...byReason.entries()].sort((left, right) => right[1] - left[1])),
|
|
323
323
|
// Scheduler single-flight suppression: wakes that were coalesced
|
|
324
324
|
// because the Role runtime lifecycle lane was busy. These are
|
|
325
|
-
// scheduler outcomes, never failed
|
|
325
|
+
// scheduler outcomes, never failed AgentRuns.
|
|
326
326
|
suppressedWakes: { status: "ok", data: suppressedWakes }
|
|
327
327
|
});
|
|
328
328
|
}
|
|
@@ -332,7 +332,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
332
332
|
})();
|
|
333
333
|
const sessions = (() => {
|
|
334
334
|
try {
|
|
335
|
-
let
|
|
335
|
+
let count = 0;
|
|
336
336
|
let broken = 0;
|
|
337
337
|
let stopped = 0;
|
|
338
338
|
let other = 0;
|
|
@@ -340,18 +340,18 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
340
340
|
let conversationSwitches = 0;
|
|
341
341
|
let lifecycleEvents = 0;
|
|
342
342
|
let stopFailures = 0;
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
343
|
+
const terminalByRunRelation = {
|
|
344
|
+
postRunCompleted: 0,
|
|
345
|
+
runFailed: 0,
|
|
346
|
+
activeRun: 0,
|
|
347
|
+
noRun: 0
|
|
348
348
|
};
|
|
349
349
|
for (const taskId of taskIds) {
|
|
350
|
-
const
|
|
350
|
+
const runs = store.listRuns(taskId);
|
|
351
351
|
for (const set of store.listRoleSessionSets(taskId)) {
|
|
352
352
|
const history = Array.isArray(set.history) ? set.history : [];
|
|
353
353
|
for (const session of [...history, ...Object.values(set.sessions)]) {
|
|
354
|
-
|
|
354
|
+
count += 1;
|
|
355
355
|
if (session.status === "ended" && session.endReason === "failed")
|
|
356
356
|
broken += 1;
|
|
357
357
|
else if (session.status === "ended")
|
|
@@ -359,7 +359,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
359
359
|
else
|
|
360
360
|
other += 1;
|
|
361
361
|
if (session.status === "ended") {
|
|
362
|
-
|
|
362
|
+
classifyTerminalSessionRunRelation(runs, set.owner.roleName, session, terminalByRunRelation);
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
}
|
|
@@ -379,7 +379,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
return ok({
|
|
382
|
-
|
|
382
|
+
count,
|
|
383
383
|
broken,
|
|
384
384
|
stopped,
|
|
385
385
|
other,
|
|
@@ -387,7 +387,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
387
387
|
conversationSwitches,
|
|
388
388
|
lifecycleEvents,
|
|
389
389
|
stopFailures,
|
|
390
|
-
|
|
390
|
+
terminalByRunRelation
|
|
391
391
|
});
|
|
392
392
|
}
|
|
393
393
|
catch (error) {
|
|
@@ -577,7 +577,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
577
577
|
entries.push({
|
|
578
578
|
taskId,
|
|
579
579
|
eventId: event.id,
|
|
580
|
-
|
|
580
|
+
runId: event.payload.runId ?? "",
|
|
581
581
|
roleName: event.payload.roleName ?? "",
|
|
582
582
|
source: event.payload.source ?? "unknown",
|
|
583
583
|
phase: event.payload.phase ?? "unknown",
|
|
@@ -591,8 +591,6 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
591
591
|
registrationDisposition: event.payload.registrationDisposition,
|
|
592
592
|
errorName: event.payload.errorName,
|
|
593
593
|
causeName: event.payload.causeName,
|
|
594
|
-
expectedRuntimeGenerationId: event.payload.expectedRuntimeGenerationId,
|
|
595
|
-
observedRuntimeGenerationId: event.payload.observedRuntimeGenerationId,
|
|
596
594
|
attemptId: event.payload.attemptId
|
|
597
595
|
}),
|
|
598
596
|
createdAt: event.createdAt
|
|
@@ -619,7 +617,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
619
617
|
if (!inWindow(item.createdAt, options))
|
|
620
618
|
continue;
|
|
621
619
|
total += 1;
|
|
622
|
-
if (item.status === "
|
|
620
|
+
if (item.status === "accepted")
|
|
623
621
|
completed += 1;
|
|
624
622
|
else if (item.status === "retired")
|
|
625
623
|
retired += 1;
|
|
@@ -639,7 +637,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
639
637
|
return [];
|
|
640
638
|
return [projectTaskOrchestration({
|
|
641
639
|
task,
|
|
642
|
-
|
|
640
|
+
runs: withinWindow(store.listRuns(taskId), options),
|
|
643
641
|
roleSessionSets: sessionSetsWithinWindow(store.listRoleSessionSets(taskId), options),
|
|
644
642
|
workItems: withinWindow(store.listWorkItems(taskId), options),
|
|
645
643
|
changeSets: withinWindow(store.listChangeSets(taskId), options),
|
|
@@ -704,7 +702,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
704
702
|
let processExitObservations = 0;
|
|
705
703
|
let compactionEvents = 0;
|
|
706
704
|
for (const taskId of taskIds) {
|
|
707
|
-
for (const run of store.
|
|
705
|
+
for (const run of store.listRuns(taskId)) {
|
|
708
706
|
if (!inWindow(run.createdAt, options))
|
|
709
707
|
continue;
|
|
710
708
|
const version = String(run.effective.contextProtocolVersion);
|
|
@@ -756,21 +754,21 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
756
754
|
try {
|
|
757
755
|
const entries = [];
|
|
758
756
|
for (const taskId of taskIds) {
|
|
759
|
-
for (const
|
|
760
|
-
if (!inWindow(
|
|
757
|
+
for (const run of store.listRuns(taskId)) {
|
|
758
|
+
if (!inWindow(run.createdAt, options))
|
|
761
759
|
continue;
|
|
762
|
-
const duration =
|
|
763
|
-
? Math.max(0, Date.now() - Date.parse(
|
|
764
|
-
: durationMs(
|
|
760
|
+
const duration = run.status === "active"
|
|
761
|
+
? Math.max(0, Date.now() - Date.parse(run.createdAt))
|
|
762
|
+
: durationMs(run);
|
|
765
763
|
if (duration <= 0)
|
|
766
764
|
continue;
|
|
767
765
|
entries.push({
|
|
768
766
|
taskId,
|
|
769
|
-
|
|
770
|
-
roleName:
|
|
771
|
-
status:
|
|
767
|
+
runId: run.id,
|
|
768
|
+
roleName: run.roleName,
|
|
769
|
+
status: run.status,
|
|
772
770
|
durationMs: duration,
|
|
773
|
-
startedAt:
|
|
771
|
+
startedAt: run.createdAt
|
|
774
772
|
});
|
|
775
773
|
}
|
|
776
774
|
}
|
|
@@ -788,7 +786,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
788
786
|
homeIdentity,
|
|
789
787
|
scope,
|
|
790
788
|
tasks,
|
|
791
|
-
|
|
789
|
+
runs,
|
|
792
790
|
wakes,
|
|
793
791
|
sessions,
|
|
794
792
|
reviews,
|
|
@@ -20,8 +20,8 @@ function excerpt(text, max = 160) {
|
|
|
20
20
|
const normalized = text.replace(/\s+/g, " ").trim();
|
|
21
21
|
return normalized.length <= max ? normalized : `${normalized.slice(0, max)}…`;
|
|
22
22
|
}
|
|
23
|
-
/** Classify a failed
|
|
24
|
-
export function
|
|
23
|
+
/** Classify a failed AgentRun without inspecting Agent-authored output. */
|
|
24
|
+
export function classifyRunFailure(run) {
|
|
25
25
|
if (run.status !== "failed")
|
|
26
26
|
return NO_FAULT;
|
|
27
27
|
const failureReason = run.result?.failureReason;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
|
-
import {
|
|
2
|
+
import { isCompletedReviewExecutionFromRuns } from "../review/reviewAcceptance.js";
|
|
3
3
|
import { projectFirstProgressAdvisory } from "../runtime/firstProgressAdvisory.js";
|
|
4
4
|
/** One Task's orchestration cost and advisory projection, with no writes. */
|
|
5
5
|
export function projectTaskOrchestration(facts) {
|
|
@@ -48,10 +48,10 @@ export function projectTaskOrchestration(facts) {
|
|
|
48
48
|
timeToFirstProjectCommitMs: firstCommitAt === undefined
|
|
49
49
|
? null
|
|
50
50
|
: Math.max(0, Date.parse(firstCommitAt) - Date.parse(facts.task.createdAt)),
|
|
51
|
-
|
|
52
|
-
total: facts.
|
|
53
|
-
byStatus: counts(facts.
|
|
54
|
-
byRole: counts(facts.
|
|
51
|
+
runs: {
|
|
52
|
+
total: facts.runs.length,
|
|
53
|
+
byStatus: counts(facts.runs.map(({ status }) => status)),
|
|
54
|
+
byRole: counts(facts.runs.map(({ roleName }) => roleName))
|
|
55
55
|
},
|
|
56
56
|
workItems: facts.workItems.length,
|
|
57
57
|
reviews: {
|
|
@@ -65,7 +65,7 @@ export function projectTaskOrchestration(facts) {
|
|
|
65
65
|
repeatedIdentities,
|
|
66
66
|
evidenceReuses: facts.integrations.filter((attempt) => ((attempt.checks ?? []).some(({ details }) => details?.startsWith("Reused successful check evidence from ")))).length
|
|
67
67
|
},
|
|
68
|
-
|
|
68
|
+
providerSessionsBeforeFirstProgress: firstProgress.sessionsBeforeFirstProgress,
|
|
69
69
|
publicationToCompletionMs: publicationAt === undefined || facts.task.completedAt === undefined
|
|
70
70
|
? null
|
|
71
71
|
: Math.max(0, Date.parse(facts.task.completedAt) - Date.parse(publicationAt)),
|
|
@@ -91,7 +91,7 @@ function projectAdvisories(facts, fullRounds, repeatedIdentities, firstProgressA
|
|
|
91
91
|
.map(({ id }) => `durable-job:${id}`)
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
|
-
const completedFull = fullRounds.filter((round) => (
|
|
94
|
+
const completedFull = fullRounds.filter((round) => (isCompletedReviewExecutionFromRuns(round, facts.runs)))
|
|
95
95
|
.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
|
|
96
96
|
const recent = completedFull.slice(-3);
|
|
97
97
|
const sameCandidate = recent.length === 3
|
|
@@ -108,7 +108,7 @@ function projectAdvisories(facts, fullRounds, repeatedIdentities, firstProgressA
|
|
|
108
108
|
if (firstProgressAttention) {
|
|
109
109
|
result.push({
|
|
110
110
|
code: "provider-first-progress-advisory",
|
|
111
|
-
reason: "Two fresh Leader
|
|
111
|
+
reason: "Two fresh Leader Sessions produced no first durable progress; consider Operator attention before another Session.",
|
|
112
112
|
refs: [facts.task.id]
|
|
113
113
|
});
|
|
114
114
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { agentAdapterLabel as adapterLabel } from "../agent/adapterCatalog.js";
|
|
1
2
|
import { normalizeRoleAgentSessionText, roleAgentSessionRef, validateRoleSessionSet } from "../executor/agentExecutor.js";
|
|
2
3
|
/** Separates the one selected writer authority from retained conversations. */
|
|
3
4
|
export function projectOperatorStatus(sessions, activeAgentId, activeAdapterId) {
|
|
@@ -141,13 +142,6 @@ function optionalDisplayText(value) {
|
|
|
141
142
|
const normalized = normalizeRoleAgentSessionText(value);
|
|
142
143
|
return normalized.length === 0 ? undefined : normalized;
|
|
143
144
|
}
|
|
144
|
-
function adapterLabel(adapterId) {
|
|
145
|
-
return adapterId === "codex"
|
|
146
|
-
? "Codex"
|
|
147
|
-
: adapterId === "claude"
|
|
148
|
-
? "Claude"
|
|
149
|
-
: adapterId;
|
|
150
|
-
}
|
|
151
145
|
function requireText(value, label) {
|
|
152
146
|
if (typeof value !== "string" || value.includes("\0") || value.trim().length === 0) {
|
|
153
147
|
throw new Error(`${label} is required.`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { renderAgentConfigurationResolutionNotice } from "../cli/agentConfigurationPicker.js";
|
|
2
|
+
import { agentHandshakeLine } from "./agentRunConfigurationPresentation.js";
|
|
2
3
|
import { defaultTableWidth, renderTable } from "./table.js";
|
|
3
4
|
export function renderAgentConfigurationCatalog(resolved) {
|
|
4
5
|
const { catalog } = resolved;
|
|
@@ -11,13 +12,17 @@ export function renderAgentConfigurationCatalog(resolved) {
|
|
|
11
12
|
model.serviceTiers?.map((tier) => tier.value).join(", ") || "none reported"
|
|
12
13
|
]);
|
|
13
14
|
const fieldRows = catalog.fields
|
|
14
|
-
.filter((field) => field.key !== "model" && field.key !== "effort")
|
|
15
|
+
.filter((field) => modelRows.length === 0 || (field.key !== "model" && field.key !== "effort"))
|
|
15
16
|
.map((field) => [
|
|
16
17
|
field.key,
|
|
17
18
|
field.choices.map((choice) => choice.value).join(", ") || "none reported",
|
|
19
|
+
// An available field can still carry a reason, and for ACP it always does:
|
|
20
|
+
// the values are enumerated per Session, so the probe deliberately lists
|
|
21
|
+
// none. Dropping that sentence left "none reported" looking like a failed
|
|
22
|
+
// query rather than a deliberate boundary, so it is shown either way.
|
|
18
23
|
field.available === false
|
|
19
24
|
? `unavailable${field.reason === undefined ? "" : `: ${field.reason}`}`
|
|
20
|
-
: "available"
|
|
25
|
+
: field.reason === undefined ? "available" : `available: ${field.reason}`,
|
|
21
26
|
field.allowCustom ? "yes" : "no"
|
|
22
27
|
]);
|
|
23
28
|
const sections = [
|
|
@@ -39,5 +44,5 @@ export function renderAgentConfigurationCatalog(resolved) {
|
|
|
39
44
|
{ header: "Custom", minWidth: 6, maxWidth: 8 }
|
|
40
45
|
], fieldRows, defaultTableWidth())])
|
|
41
46
|
];
|
|
42
|
-
return `${sections.join("\n\n")}\n${renderAgentConfigurationResolutionNotice(resolved)}`;
|
|
47
|
+
return `${sections.join("\n\n")}\n${agentHandshakeLine(catalog.handshake)}\n${renderAgentConfigurationResolutionNotice(resolved)}`;
|
|
43
48
|
}
|