@zq-silk/yui 0.15.7 → 0.15.8
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 +192 -399
- package/README.md +127 -1149
- 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/brief/taskBrief.js +12 -0
- package/dist/cli/agentConfigurationPicker.js +13 -0
- package/dist/cli/commandCatalog.js +157 -70
- 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 +178 -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 +1 -7
- 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 +259 -0
- package/dist/commands/taskActor.js +28 -49
- package/dist/commands/taskCommands.js +1188 -710
- 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} +146 -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 +458 -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 +114 -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 +247 -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 +62 -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 +380 -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 +123 -0
- package/dist/resources/projectResourceService.js +421 -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 +1 -0
- package/dist/storage/migrations/agentRunContract.js +159 -0
- package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
- package/dist/storage/sqliteSchema.js +431 -5
- package/dist/storage/sqliteStore.js +375 -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 +301 -0
- package/dist/task/taskActivationService.js +392 -0
- package/dist/task/taskRecordReference.js +5 -4
- package/dist/task/taskRecordRetirement.js +1 -1
- 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 +120 -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 +353 -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 +118 -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 +80 -48
- package/dist/workspace/workItemChangeSetManager.js +16 -9
- package/docs/agent-result-consumption.md +94 -0
- package/docs/agent-runtime-drivers.md +91 -0
- package/docs/architecture/README.md +38 -0
- package/docs/architecture/capabilities-and-resources.md +79 -0
- package/docs/managed-turn-and-session-runtime.md +222 -0
- package/docs/observability/README.md +81 -0
- package/docs/plugin-sdk.md +290 -0
- package/docs/provider-runtime.md +163 -0
- package/docs/release-workflow.md +303 -0
- package/docs/roles-and-configuration.md +113 -0
- package/docs/sqlite-control-plane-design.md +76 -0
- package/docs/task-dag-semantics.md +57 -0
- package/docs/task-delivery.md +103 -0
- package/docs/task-local-identity.md +6 -6
- package/docs/testing/verification-levels.md +86 -0
- package/i18n/README.zh-CN.md +98 -739
- package/package.json +2 -2
- package/skills/yui-leader/SKILL.md +130 -103
- package/skills/yui-leader/references/integration.md +39 -0
- package/skills/yui-leader/references/replicated-execution.md +42 -0
- package/skills/yui-leader/references/task-plugins.md +33 -0
- package/skills/yui-operator/SKILL.md +30 -59
- 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
package/dist/storage/storeRpc.js
CHANGED
|
@@ -28,6 +28,9 @@ import { StorageCancelledError, StorageConflictError, StorageRecordError } from
|
|
|
28
28
|
* else is routed to the writer connection.
|
|
29
29
|
*/
|
|
30
30
|
const READ_ONLY_STORE_METHODS = new Set([
|
|
31
|
+
"getPluginIntent", "listPluginIntents",
|
|
32
|
+
"getPluginValidation", "getArtifact", "listArtifacts", "getLocalResource", "listLocalResources",
|
|
33
|
+
"getEnvironmentPreparation", "listEnvironmentPreparations",
|
|
31
34
|
"rootDirectory",
|
|
32
35
|
"getConfig",
|
|
33
36
|
"getHomeIdentity",
|
|
@@ -48,6 +51,8 @@ const READ_ONLY_STORE_METHODS = new Set([
|
|
|
48
51
|
"readNextActionFacts",
|
|
49
52
|
"readCompletionReadinessFacts",
|
|
50
53
|
"listActiveTaskIds",
|
|
54
|
+
"listPlanningDraftTaskIds",
|
|
55
|
+
"listPendingActivationRequestTaskIds",
|
|
51
56
|
"getTaskBrief",
|
|
52
57
|
"listChangeSets",
|
|
53
58
|
"getChangeSet",
|
|
@@ -70,13 +75,13 @@ const READ_ONLY_STORE_METHODS = new Set([
|
|
|
70
75
|
"getRoleSession",
|
|
71
76
|
"getWorkItem",
|
|
72
77
|
"listWorkItems",
|
|
73
|
-
"
|
|
74
|
-
"
|
|
78
|
+
"getRun",
|
|
79
|
+
"listRuns",
|
|
75
80
|
"listPendingProviderRetries",
|
|
76
|
-
"
|
|
81
|
+
"peekNextRunId",
|
|
77
82
|
"getReviewRound",
|
|
78
|
-
"
|
|
79
|
-
"
|
|
83
|
+
"getActiveRun",
|
|
84
|
+
"getActiveExecutionLaneRun",
|
|
80
85
|
"listMessages",
|
|
81
86
|
"getInputRequest",
|
|
82
87
|
"listInputRequests",
|
|
@@ -5,14 +5,14 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
5
5
|
import { validateCapabilityGrant } from "../grant/capabilityGrant.js";
|
|
6
6
|
import { validateReleaseWorkflow } from "../release/releaseWorkflow.js";
|
|
7
7
|
import { validatePublicationReference } from "../task/publicationReference.js";
|
|
8
|
-
import { reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveLeaderNextActionMode,
|
|
8
|
+
import { reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveLeaderNextActionMode, resolveLeaderSemanticBudgetRuns, resolveResourcesGcAutoQuarantine, resolveResourcesGcMode, resolveResourcesQuarantineTtlHours, resolveRuntimeHealth, resolveTelemetryEnabled, resolveTelemetryRunCap, resolveTelemetryTerminalKeep, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
|
|
9
9
|
import { resolveTimeZone } from "../output/timePresentation.js";
|
|
10
10
|
import { validateReviewConfig } from "../review/reviewConfig.js";
|
|
11
11
|
import { validateTaskRecordReference } from "../task/taskRecordReference.js";
|
|
12
12
|
export const CURRENT_CONFIG_SCHEMA_VERSION = 6;
|
|
13
13
|
/** Current SQLite payload-family versions owned by this storage boundary. */
|
|
14
14
|
export const CURRENT_CONFIGURED_AGENT_SCHEMA_VERSION = 2;
|
|
15
|
-
export const CURRENT_PROJECT_SCHEMA_VERSION =
|
|
15
|
+
export const CURRENT_PROJECT_SCHEMA_VERSION = 6;
|
|
16
16
|
export const CURRENT_AGENT_PROFILE_SCHEMA_VERSION = 3;
|
|
17
17
|
export const CURRENT_GLOBAL_ROLE_SCHEMA_VERSION = 3;
|
|
18
18
|
export const CURRENT_GLOBAL_ROLE_SESSION_SET_SCHEMA_VERSION = 5;
|
|
@@ -42,13 +42,13 @@ export const COMPLETION_SHELLS = ["bash", "zsh", "fish"];
|
|
|
42
42
|
* makes the two key spaces disjoint even for legal Role names such as
|
|
43
43
|
* `lane:worker:1`.
|
|
44
44
|
*/
|
|
45
|
-
export function
|
|
45
|
+
export function executionLaneActiveRunKey(executionGroupId, executionLaneId) {
|
|
46
46
|
return `/execution-lane/${encodeLaneKeyPart(executionGroupId)}:${encodeLaneKeyPart(executionLaneId)}`;
|
|
47
47
|
}
|
|
48
48
|
function encodeLaneKeyPart(value) {
|
|
49
49
|
return encodeURIComponent(value).replace(/:/gu, "%3A");
|
|
50
50
|
}
|
|
51
|
-
export function
|
|
51
|
+
export function executionLaneActiveRunKeyParts(key) {
|
|
52
52
|
const match = /^\/execution-lane\/([^:]+):([^:]+)$/u.exec(key);
|
|
53
53
|
if (match === null)
|
|
54
54
|
return null;
|
|
@@ -66,7 +66,7 @@ export function executionLaneActiveTurnKeyParts(key) {
|
|
|
66
66
|
* Nested-record versions consumed by the current SQLite payload validators.
|
|
67
67
|
*/
|
|
68
68
|
export const CURRENT_TASK_ROLE_SESSION_SET_SCHEMA_VERSION = 12;
|
|
69
|
-
export const
|
|
69
|
+
export const CURRENT_RUN_SCHEMA_VERSION = 5;
|
|
70
70
|
export const CURRENT_INTEGRATION_QUEUE_SCHEMA_VERSION = 1;
|
|
71
71
|
export class StorageRecordError extends Error {
|
|
72
72
|
constructor(message) { super(message); this.name = "StorageRecordError"; }
|
|
@@ -156,13 +156,13 @@ export function validateYuiConfig(config) {
|
|
|
156
156
|
"controllerTaskConcurrency",
|
|
157
157
|
"agentLaunchInactivityTimeoutSeconds",
|
|
158
158
|
"deliveryTimeoutSeconds",
|
|
159
|
-
"
|
|
159
|
+
"leaderSemanticBudgetRuns",
|
|
160
160
|
"resourcesQuarantineTtlHours",
|
|
161
161
|
"tmuxBin",
|
|
162
162
|
"tmuxHistoryLimit",
|
|
163
163
|
"telemetryEnabled",
|
|
164
164
|
"telemetryTerminalKeep",
|
|
165
|
-
"
|
|
165
|
+
"telemetryRunCap",
|
|
166
166
|
"completionInstallations"
|
|
167
167
|
];
|
|
168
168
|
exact(config, [
|
|
@@ -184,12 +184,12 @@ export function validateYuiConfig(config) {
|
|
|
184
184
|
resolveControllerTaskConcurrency(config.controllerTaskConcurrency);
|
|
185
185
|
resolveAgentLaunchInactivityTimeoutSeconds(config.agentLaunchInactivityTimeoutSeconds);
|
|
186
186
|
resolveDeliveryTimeoutSeconds(config.deliveryTimeoutSeconds);
|
|
187
|
-
|
|
187
|
+
resolveLeaderSemanticBudgetRuns(config.leaderSemanticBudgetRuns);
|
|
188
188
|
resolveTmuxBin(config.tmuxBin);
|
|
189
189
|
resolveTmuxHistoryLimit(config.tmuxHistoryLimit);
|
|
190
190
|
resolveTelemetryEnabled(config.telemetryEnabled);
|
|
191
191
|
resolveTelemetryTerminalKeep(config.telemetryTerminalKeep);
|
|
192
|
-
|
|
192
|
+
resolveTelemetryRunCap(config.telemetryRunCap);
|
|
193
193
|
}
|
|
194
194
|
catch (error) {
|
|
195
195
|
throw new StorageRecordError(error instanceof Error ? error.message : "Yui reconciliation interval is invalid.");
|
|
@@ -350,7 +350,8 @@ export function isValidCapabilityGrantTransition(existing, candidate) {
|
|
|
350
350
|
}
|
|
351
351
|
// A use record must advance the counter (compare-and-swap): a stale equal
|
|
352
352
|
// increment from a concurrent reader is rejected, so two workflows cannot
|
|
353
|
-
// spend the same maxUses slot.
|
|
353
|
+
// spend the same maxUses slot. Existing reservations are append-only;
|
|
354
|
+
// non-resumable uses may advance the counter without adding a reservation.
|
|
354
355
|
return candidate.usesUsed > existing.usesUsed
|
|
355
356
|
&& reservationsAppendOnly(existing.useReservations, candidate.useReservations)
|
|
356
357
|
&& Date.parse(candidate.updatedAt) >= Date.parse(existing.updatedAt);
|
|
@@ -702,7 +703,8 @@ function assertJsonValue(value, label, seen = new Set()) {
|
|
|
702
703
|
}
|
|
703
704
|
function clone(value) { assertJsonValue(value, "Stored value"); return JSON.parse(JSON.stringify(value)); }
|
|
704
705
|
export function pendingWakeupProjection(mailbox) {
|
|
705
|
-
const pending = mailbox?.processing?.owner.startsWith("leader-steer:") === true
|
|
706
|
+
const pending = (mailbox?.processing?.owner.startsWith("leader-steer:") === true
|
|
707
|
+
|| mailbox?.processing?.owner.startsWith("leader-notification:") === true)
|
|
706
708
|
? mailbox.processing.batch
|
|
707
709
|
: mailbox?.pending ?? null;
|
|
708
710
|
if (mailbox === null || mailbox.target.kind !== "role" || mailbox.target.roleName !== "leader"
|
|
@@ -6,7 +6,7 @@ import { RUNTIME_PROCESS_EXIT_TASK_EVENT, validateRuntimeProcessExitObservation
|
|
|
6
6
|
import { validateAgentProfile } from "../../profile/agentProfile.js";
|
|
7
7
|
import { validateRoleSessionSet } from "../../executor/agentExecutor.js";
|
|
8
8
|
import { validateReviewRound } from "../../review/reviewRound.js";
|
|
9
|
-
import {
|
|
9
|
+
import { validateRun } from "../../agentRun/agentRun.js";
|
|
10
10
|
import { validateDurableJob } from "../../job/durableJob.js";
|
|
11
11
|
import { validateWorkItem } from "../../workItem/workItem.js";
|
|
12
12
|
import { SqliteTaskStore } from "../sqliteStore.js";
|
|
@@ -185,10 +185,8 @@ function validateCurrentStore(home) {
|
|
|
185
185
|
validateRoleSessionSet(sessions);
|
|
186
186
|
}
|
|
187
187
|
for (const owner of store.listSessionOwners()) {
|
|
188
|
-
if (owner.schemaVersion !== 2
|
|
189
|
-
|
|
190
|
-
|| Object.hasOwn(owner, "launchId")) {
|
|
191
|
-
throw new Error("Session owner runtime generation identity is invalid.");
|
|
188
|
+
if (owner.schemaVersion !== 2 || Object.hasOwn(owner, "launchId")) {
|
|
189
|
+
throw new Error("Session owner runtime identity is invalid.");
|
|
192
190
|
}
|
|
193
191
|
}
|
|
194
192
|
for (const taskId of store.listTasks().map(({ id }) => id)) {
|
|
@@ -198,8 +196,8 @@ function validateCurrentStore(home) {
|
|
|
198
196
|
validateWorkItem(item);
|
|
199
197
|
for (const round of store.listReviewRounds(taskId))
|
|
200
198
|
validateReviewRound(round);
|
|
201
|
-
for (const
|
|
202
|
-
|
|
199
|
+
for (const run of store.listRuns(taskId))
|
|
200
|
+
validateRun(run);
|
|
203
201
|
for (const sessions of store.listRoleSessionSets(taskId)) {
|
|
204
202
|
validateRoleSessionSet(sessions);
|
|
205
203
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/** A fresh authorized view, not a second directory or instance ledger.
|
|
2
|
+
* Capabilities naturally contribute CLI commands; queries also get the known
|
|
3
|
+
* JSON renderer unless the provider supplies a controlled panel descriptor. */
|
|
4
|
+
export class SurfaceContributions {
|
|
5
|
+
registry;
|
|
6
|
+
constructor(registry) {
|
|
7
|
+
this.registry = registry;
|
|
8
|
+
}
|
|
9
|
+
listCommands(context) {
|
|
10
|
+
return this.registry.search(context).map((entry) => ({
|
|
11
|
+
...reference(entry), name: entry.surfaces?.cli?.name ?? entry.name,
|
|
12
|
+
help: entry.surfaces?.cli?.help ?? entry.summary, effect: entry.effect,
|
|
13
|
+
...(entry.unavailable === undefined ? {} : { unavailable: entry.unavailable })
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
listPanels(context) {
|
|
17
|
+
return this.registry.search(context).flatMap((entry) => {
|
|
18
|
+
const panel = entry.surfaces?.panel
|
|
19
|
+
?? (entry.effect === "query" ? { kind: "data", title: entry.summary, renderer: "json" } : undefined);
|
|
20
|
+
return panel ? [{
|
|
21
|
+
...reference(entry), panel, inputSchema: entry.inputSchema,
|
|
22
|
+
...(entry.unavailable === undefined ? {} : { unavailable: entry.unavailable })
|
|
23
|
+
}] : [];
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/** Query entry used by the Controller-owned Web server. Resolve the current
|
|
27
|
+
* descriptor and exact generation again; the browser never supplies code. */
|
|
28
|
+
readPanel(context, selected, input) {
|
|
29
|
+
const resolved = this.registry.describe(context, {
|
|
30
|
+
name: selected.capability, contractVersion: selected.contractVersion, providerId: selected.provider.id
|
|
31
|
+
});
|
|
32
|
+
if (resolved.kind !== "value")
|
|
33
|
+
return Promise.resolve(resolved);
|
|
34
|
+
const descriptor = resolved.value;
|
|
35
|
+
if (descriptor.provider.generation !== selected.provider.generation || descriptor.effect !== "query") {
|
|
36
|
+
return Promise.resolve({ kind: "unavailable", effect: "none", operations: [],
|
|
37
|
+
detail: "Panel changed or is not a query. Reload current panels." });
|
|
38
|
+
}
|
|
39
|
+
const panel = descriptor.surfaces?.panel;
|
|
40
|
+
if (panel !== undefined && panel.kind !== "data")
|
|
41
|
+
return Promise.resolve({ ...resolved, value: panel });
|
|
42
|
+
return this.registry.call(context, {
|
|
43
|
+
name: descriptor.name, contractVersion: descriptor.contractVersion,
|
|
44
|
+
providerId: descriptor.provider.id, input
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Called before a complete capability generation is published. Restrict the
|
|
49
|
+
* entire accepted shape so unchecked HTML or executable fields cannot sneak
|
|
50
|
+
* into the browser's descriptor payload. */
|
|
51
|
+
export function checkSurfaceDescriptors(entry) {
|
|
52
|
+
if (entry.surfaces === undefined)
|
|
53
|
+
return;
|
|
54
|
+
const surfaces = record(entry.surfaces, ["cli", "panel"]);
|
|
55
|
+
if (surfaces.cli !== undefined) {
|
|
56
|
+
const cli = record(surfaces.cli, ["name", "help"]);
|
|
57
|
+
// Command names are the capability's existing namespace, not root commands
|
|
58
|
+
// or a second alias-resolution policy.
|
|
59
|
+
if (cli.name !== entry.name || !text(cli.help))
|
|
60
|
+
throw new Error("Invalid CLI contribution.");
|
|
61
|
+
}
|
|
62
|
+
if (surfaces.panel !== undefined) {
|
|
63
|
+
const panel = record(surfaces.panel, ["kind", "title", "text", "href", "renderer"]);
|
|
64
|
+
if (!text(panel.title))
|
|
65
|
+
throw new Error("Invalid panel title.");
|
|
66
|
+
switch (panel.kind) {
|
|
67
|
+
case "text":
|
|
68
|
+
record(panel, ["kind", "title", "text"]);
|
|
69
|
+
if (typeof panel.text !== "string")
|
|
70
|
+
throw new Error("Invalid text panel.");
|
|
71
|
+
break;
|
|
72
|
+
case "link": {
|
|
73
|
+
record(panel, ["kind", "title", "href"]);
|
|
74
|
+
if (!text(panel.href))
|
|
75
|
+
throw new Error("Invalid link panel.");
|
|
76
|
+
const url = new URL(panel.href);
|
|
77
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) {
|
|
78
|
+
throw new Error("Panel links require an HTTP(S) URL without credentials.");
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case "data":
|
|
83
|
+
record(panel, ["kind", "title", "renderer"]);
|
|
84
|
+
if (entry.effect !== "query" || panel.renderer !== "json")
|
|
85
|
+
throw new Error("Invalid data panel.");
|
|
86
|
+
break;
|
|
87
|
+
default: throw new Error("Unknown panel kind.");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function reference(entry) {
|
|
92
|
+
return { capability: entry.name, contractVersion: entry.contractVersion, provider: entry.provider };
|
|
93
|
+
}
|
|
94
|
+
function text(value) {
|
|
95
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
96
|
+
}
|
|
97
|
+
function record(value, keys) {
|
|
98
|
+
if (!value || typeof value !== "object" || Array.isArray(value)
|
|
99
|
+
|| Object.keys(value).some((key) => !keys.includes(key)))
|
|
100
|
+
throw new Error("Invalid surface descriptor.");
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import { governingWorkItemDeliveries, integrationAttemptRequiresSettlement, workItemDeliverySettled } from "../integration/deliveryObligation.js";
|
|
2
|
+
import { operationalTaskRecords } from "./taskRecordRetirement.js";
|
|
3
|
+
/** Mailbox refs locate original durable user intent. No separate acknowledgement
|
|
4
|
+
* state is introduced: finish the current native turn and let the existing
|
|
5
|
+
* notification delivery present the new input before declaring completion. */
|
|
6
|
+
export function pendingCompletionMessages(store, taskId) {
|
|
7
|
+
const mailbox = store.getWorkMailbox({ kind: "role", taskId, roleName: "leader" });
|
|
8
|
+
const refs = [...(mailbox?.pending?.refs ?? [])];
|
|
9
|
+
const processing = mailbox?.processing;
|
|
10
|
+
if (processing?.owner.startsWith("leader-notification:")) {
|
|
11
|
+
const native = store.getTaskRoleSessionSet(taskId, "leader")?.providerBinding?.run;
|
|
12
|
+
if (native?.attemptId !== processing.batchId
|
|
13
|
+
|| !["accepted", "completed", "failed", "cancelled"].includes(native.status)) {
|
|
14
|
+
refs.push(...processing.batch.refs);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const ids = new Set(refs.filter(ref => ref.type === "message" && ref.taskId === taskId).map(ref => ref.id));
|
|
18
|
+
return operationalTaskRecords(store.listMessages(taskId), store.listEvents(taskId), "message")
|
|
19
|
+
.filter(message => ids.has(message.id)
|
|
20
|
+
&& (message.kind === "user" || message.kind === "operator") && message.wakePolicy !== "none");
|
|
21
|
+
}
|
|
2
22
|
const ACTIVE_JOB_STATUSES = new Set([
|
|
3
23
|
"queued",
|
|
4
24
|
"running",
|
|
@@ -15,6 +35,14 @@ export function projectCompletionReadiness(facts) {
|
|
|
15
35
|
const blockers = [];
|
|
16
36
|
const advisories = [];
|
|
17
37
|
const { task } = facts;
|
|
38
|
+
for (const message of facts.pendingUserMessages ?? []) {
|
|
39
|
+
blockers.push({
|
|
40
|
+
code: "pending-user-input",
|
|
41
|
+
ref: ref("message", message.id),
|
|
42
|
+
reason: `User message ${message.id} is still awaiting Leader delivery.`,
|
|
43
|
+
fix: `finish the current native turn, read the next notification and message ${message.id}, then reconsider completion`
|
|
44
|
+
});
|
|
45
|
+
}
|
|
18
46
|
// A pending/running Task-final Review must be resumed or blocked first.
|
|
19
47
|
for (const round of facts.reviewRounds) {
|
|
20
48
|
if ((round.scope ?? "work-item") !== "task")
|
|
@@ -27,7 +55,7 @@ export function projectCompletionReadiness(facts) {
|
|
|
27
55
|
reason: `Task-final ReviewRound ${round.id} is ${round.status}.`,
|
|
28
56
|
fix: round.status === "pending"
|
|
29
57
|
? `yui task review retry ${task.id}/${round.id}`
|
|
30
|
-
: `wait for Reviewer
|
|
58
|
+
: `wait for Reviewer AgentRun on ${round.id} to finish`
|
|
31
59
|
});
|
|
32
60
|
}
|
|
33
61
|
// Open Input requests block protocol convergence.
|
|
@@ -41,15 +69,13 @@ export function projectCompletionReadiness(facts) {
|
|
|
41
69
|
}
|
|
42
70
|
// Every Work Item must be terminal (completed or retired).
|
|
43
71
|
for (const item of facts.workItems) {
|
|
44
|
-
if (item.status === "
|
|
72
|
+
if (item.status === "accepted" || item.status === "retired")
|
|
45
73
|
continue;
|
|
46
74
|
blockers.push({
|
|
47
75
|
code: "incomplete-work-item",
|
|
48
76
|
ref: ref("work-item", item.id),
|
|
49
77
|
reason: `Work Item ${item.id} is ${item.status}.`,
|
|
50
|
-
fix: item.
|
|
51
|
-
? `yui task work update ${task.id}/${item.id} running`
|
|
52
|
-
: `complete or retire Work Item ${item.id}`
|
|
78
|
+
fix: `accept or retire Work Item ${item.id}`
|
|
53
79
|
});
|
|
54
80
|
}
|
|
55
81
|
// Active DurableJobs (integration checks, etc.) must settle.
|
|
@@ -152,7 +178,7 @@ function workspaceCompletionDisposition(facts, taskId, workspace) {
|
|
|
152
178
|
reason: `Work Item ${owner.workItemId} has an isolated workspace that is not disposed.`,
|
|
153
179
|
fix: `yui task work cleanup ${taskId}/${owner.workItemId} --integrated|--abandon`
|
|
154
180
|
};
|
|
155
|
-
return item !== undefined && (item.status === "
|
|
181
|
+
return item !== undefined && (item.status === "accepted" || item.status === "retired")
|
|
156
182
|
? { kind: "advisory", value }
|
|
157
183
|
: { kind: "blocker", value };
|
|
158
184
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const OPEN_WORK_ITEM_STATUSES = new Set(["
|
|
1
|
+
import { isCompletedTaskReviewEvidenceFromRuns } from "../review/reviewAcceptance.js";
|
|
2
|
+
const OPEN_WORK_ITEM_STATUSES = new Set(["open"]);
|
|
3
3
|
export function detectDeliveryDuplicates(facts, intent) {
|
|
4
4
|
switch (intent.kind) {
|
|
5
5
|
case "create-work-item":
|
|
@@ -59,7 +59,7 @@ function detectWorkItemDuplicates(facts, scope) {
|
|
|
59
59
|
});
|
|
60
60
|
continue;
|
|
61
61
|
}
|
|
62
|
-
if (sameScope && item.status === "
|
|
62
|
+
if (sameScope && item.status === "accepted") {
|
|
63
63
|
duplicates.push({
|
|
64
64
|
severity: "suspected",
|
|
65
65
|
reason: `Work Item ${item.id} already delivered the identical scope; re-creating it may be a duplicate successor`,
|
|
@@ -127,7 +127,7 @@ function detectReviewDuplicates(facts, intent) {
|
|
|
127
127
|
if (!sameCandidate)
|
|
128
128
|
continue;
|
|
129
129
|
const ref = { kind: "review-round", id: round.id };
|
|
130
|
-
if (
|
|
130
|
+
if (isCompletedTaskReviewEvidenceFromRuns(round, facts.reviewOutcomeEvidence?.runs ?? [])) {
|
|
131
131
|
duplicates.push({
|
|
132
132
|
severity: "exact",
|
|
133
133
|
reason: `Task-final Review ${round.id} already attests this exact head`,
|
|
@@ -174,29 +174,29 @@ function overlap(left, right) {
|
|
|
174
174
|
* Default number of consecutive completed Leader turns that must produce no
|
|
175
175
|
* durable delivery change before the budget is exhausted.
|
|
176
176
|
*/
|
|
177
|
-
export const
|
|
177
|
+
export const DEFAULT_SEMANTIC_BUDGET_RUNS = 3;
|
|
178
178
|
/**
|
|
179
179
|
* Evaluate the semantic-progress budget from existing records only. The
|
|
180
|
-
* budget is exhausted when the last `
|
|
180
|
+
* budget is exhausted when the last `runs` Leader AgentRuns all completed and no
|
|
181
181
|
* WorkItem/ChangeSet/Integration/Review record changed at or after the first
|
|
182
|
-
* of those
|
|
182
|
+
* of those AgentRuns. Active execution (any AgentRun) never exhausts the budget: a
|
|
183
183
|
* slow but progressing Worker or Leader is never interrupted.
|
|
184
184
|
*/
|
|
185
|
-
export function evaluateSemanticBudget(facts,
|
|
186
|
-
if (facts.
|
|
185
|
+
export function evaluateSemanticBudget(facts, runs = DEFAULT_SEMANTIC_BUDGET_RUNS) {
|
|
186
|
+
if (facts.activeRuns.length > 0) {
|
|
187
187
|
return {
|
|
188
188
|
exhausted: false,
|
|
189
|
-
reason: "Active execution is in flight; the budget never interrupts a progressing
|
|
190
|
-
evidence: facts.
|
|
189
|
+
reason: "Active execution is in flight; the budget never interrupts a progressing AgentRun.",
|
|
190
|
+
evidence: facts.activeRuns.map((run) => run.id)
|
|
191
191
|
};
|
|
192
192
|
}
|
|
193
|
-
const recentLeaderRuns = facts.
|
|
193
|
+
const recentLeaderRuns = facts.leaderRuns
|
|
194
194
|
.filter((run) => run.status === "completed")
|
|
195
|
-
.slice(-
|
|
196
|
-
if (recentLeaderRuns.length <
|
|
195
|
+
.slice(-runs);
|
|
196
|
+
if (recentLeaderRuns.length < runs) {
|
|
197
197
|
return {
|
|
198
198
|
exhausted: false,
|
|
199
|
-
reason: `Fewer than ${
|
|
199
|
+
reason: `Fewer than ${runs} consecutive completed Leader runs.`,
|
|
200
200
|
evidence: recentLeaderRuns.map((run) => run.id)
|
|
201
201
|
};
|
|
202
202
|
}
|
|
@@ -211,7 +211,7 @@ export function evaluateSemanticBudget(facts, turns = DEFAULT_SEMANTIC_BUDGET_TU
|
|
|
211
211
|
}
|
|
212
212
|
return {
|
|
213
213
|
exhausted: true,
|
|
214
|
-
reason: `${
|
|
214
|
+
reason: `${runs} consecutive Leader runs produced no durable delivery change; record a diagnosis and wait for new facts instead of creating more records.`,
|
|
215
215
|
evidence: recentLeaderRuns.map((run) => run.id)
|
|
216
216
|
};
|
|
217
217
|
}
|
package/dist/task/draftPlan.js
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
import { RUNTIME_OBSERVATION_TASK_EVENT } from "../runtime/runtimeObservation.js";
|
|
2
|
+
import { SYSTEM_LEADER_ROLE } from "../role/systemRoles.js";
|
|
3
|
+
/**
|
|
4
|
+
* Runtime Task-event types that are emitted with a Role but no Turn in their
|
|
5
|
+
* payload. Each one is still only exempted when its `roleName` resolves to the
|
|
6
|
+
* Leader — the `runtime.` prefix is never exempted, and a type absent from this
|
|
7
|
+
* set keeps disqualifying the Draft.
|
|
8
|
+
*
|
|
9
|
+
* Turn lifecycle events are deliberately not listed: they use one generic type
|
|
10
|
+
* per transition and name the Turn in their payload, so the guard resolves that
|
|
11
|
+
* Turn's own purpose instead of trusting the type. Listing invented
|
|
12
|
+
* `turn.planning-*` types would have exempted nothing while silently
|
|
13
|
+
* disqualifying every Draft that ever held a planning conversation.
|
|
14
|
+
*/
|
|
15
|
+
export const PLANNING_ROLE_EVENT_TYPES = new Set([
|
|
16
|
+
"runtime.session-stop-requested",
|
|
17
|
+
"runtime.session-termination",
|
|
18
|
+
// Written by the liveness/host-exit paths, which admit a Draft planning Turn.
|
|
19
|
+
// Its payload carries the Role and embeds the Turn only inside the serialized
|
|
20
|
+
// observation, so it is resolved as Role-scoped rather than by that blob.
|
|
21
|
+
"runtime.process-exit-observed"
|
|
22
|
+
]);
|
|
1
23
|
export function assertDraftTaskExecutionFree(store, task) {
|
|
2
24
|
if (task.status !== "draft") {
|
|
3
25
|
throw new Error(`Task is not a Draft: ${task.id}/${task.status}.`);
|
|
@@ -109,13 +131,21 @@ function assertDraftWorkItemDependencyGraph(workItems, onlyItem) {
|
|
|
109
131
|
function firstDraftExecutionFact(store, task) {
|
|
110
132
|
if (task.workspaceIdentity !== undefined || task.cwd !== undefined)
|
|
111
133
|
return "Task workspace";
|
|
112
|
-
|
|
134
|
+
// Draft planning is a first-class Leader conversation, so its Turns, its
|
|
135
|
+
// Session and its Host are ordinary planning facts rather than execution
|
|
136
|
+
// history. Anything that could only exist after delivery still disqualifies
|
|
137
|
+
// the Draft, and a planning Turn can never carry a WorkItem, ReviewRound,
|
|
138
|
+
// Lane or workspace (validateTurn enforces that), so this stays a narrow
|
|
139
|
+
// exemption rather than a hole.
|
|
140
|
+
const run = store.listRuns(task.id).find(({ purpose }) => purpose !== "planning");
|
|
141
|
+
if (run !== undefined)
|
|
142
|
+
return `AgentRun ${run.id}/${run.purpose}`;
|
|
143
|
+
const hostOwner = store.listSessionOwners().find(({ owner }) => (owner.scope === "task" && owner.taskId === task.id && owner.roleName !== SYSTEM_LEADER_ROLE));
|
|
113
144
|
if (hostOwner !== undefined)
|
|
114
|
-
return `Host
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return "Role Session";
|
|
145
|
+
return `Host process (${hostOwner.providerRoot.pid})`;
|
|
146
|
+
const sessionSet = store.listRoleSessionSets(task.id).find(({ owner }) => owner.roleName !== SYSTEM_LEADER_ROLE);
|
|
147
|
+
if (sessionSet !== undefined)
|
|
148
|
+
return `Role Session (${sessionSet.owner.roleName})`;
|
|
119
149
|
if (store.listDurableJobs(task.id).length > 0)
|
|
120
150
|
return "DurableJob";
|
|
121
151
|
if (store.listManagedWorkspaces(task.id).length > 0)
|
|
@@ -130,13 +160,43 @@ function firstDraftExecutionFact(store, task) {
|
|
|
130
160
|
|| item.currentExecutionGroupId !== undefined
|
|
131
161
|
|| item.candidates.length > 0
|
|
132
162
|
|| item.workspaceDisposition !== undefined
|
|
133
|
-
|| !["
|
|
163
|
+
|| !["open", "retired"].includes(item.status)));
|
|
134
164
|
if (itemWithExecution !== undefined) {
|
|
135
165
|
return `Work Item execution (${itemWithExecution.id})`;
|
|
136
166
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
167
|
+
// Runtime observations support planning; they are not a competing source
|
|
168
|
+
// of delivery authority. The domain records above own delivery facts.
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Whether one runtime/Turn Task event belongs to this Draft's own planning
|
|
173
|
+
* conversation.
|
|
174
|
+
*
|
|
175
|
+
* The binding the event carries decides this, never its type prefix:
|
|
176
|
+
*
|
|
177
|
+
* - it names a Turn → that Turn must exist on this Task and be `planning`;
|
|
178
|
+
* - it names no Turn → its exact type must be Role-scoped by construction and
|
|
179
|
+
* its `roleName` must be the Leader, the only Role a Draft may run.
|
|
180
|
+
*
|
|
181
|
+
* Everything else stays disqualifying, so an unrecognized type, a foreign Role
|
|
182
|
+
* or a Turn reference that cannot be resolved fails closed.
|
|
183
|
+
*/
|
|
184
|
+
function isDraftPlanningEvent(store, task, event) {
|
|
185
|
+
// Several emitters write an absent Turn as an empty string, so only a
|
|
186
|
+
// non-empty id counts as a reference worth resolving.
|
|
187
|
+
const runId = event.payload["runId"];
|
|
188
|
+
if (typeof runId === "string" && runId !== "") {
|
|
189
|
+
return store.getRun(task.id, runId)?.purpose === "planning";
|
|
190
|
+
}
|
|
191
|
+
// A canonical runtime observation is the event normal delivery writes for
|
|
192
|
+
// session.started/conversation.observed/turn.accepted and every terminal. It
|
|
193
|
+
// names its Turn in the same payload field as everything else and was
|
|
194
|
+
// resolved above; only an unfenced host-level observation reaches here, where
|
|
195
|
+
// the Role still has to prove it. Admitting this one type by its own binding
|
|
196
|
+
// is not the same as admitting the `runtime.` prefix.
|
|
197
|
+
if (event.type !== RUNTIME_OBSERVATION_TASK_EVENT
|
|
198
|
+
&& !PLANNING_ROLE_EVENT_TYPES.has(event.type)) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
return event.payload["roleName"] === SYSTEM_LEADER_ROLE;
|
|
142
202
|
}
|