@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.
Files changed (308) hide show
  1. package/ARCHITECTURE.md +194 -399
  2. package/ARCHITECTURE.zh-CN.md +151 -0
  3. package/README.md +306 -1131
  4. package/dist/agent/adapterCatalog.js +15 -2
  5. package/dist/agent/agent.js +23 -3
  6. package/dist/agent/argumentPolicy.js +7 -1
  7. package/dist/agent/connectionPlan.js +62 -0
  8. package/dist/agent/executionComponents.js +158 -0
  9. package/dist/agent/launchEnvironment.js +31 -3
  10. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  11. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  12. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  13. package/dist/artifacts/artifactCapability.js +74 -0
  14. package/dist/artifacts/artifactCommitLock.js +249 -0
  15. package/dist/artifacts/artifactPaths.js +151 -0
  16. package/dist/artifacts/gitArtifactRef.js +146 -0
  17. package/dist/artifacts/managedGit.js +332 -0
  18. package/dist/artifacts/taskArtifactRepository.js +277 -0
  19. package/dist/brief/taskBrief.js +12 -0
  20. package/dist/cli/agentConfigurationPicker.js +13 -0
  21. package/dist/cli/commandCatalog.js +165 -74
  22. package/dist/cli/interactionCandidates.js +5 -5
  23. package/dist/cli/interactionPolicy.js +38 -8
  24. package/dist/cli/invocationRouter.js +1 -1
  25. package/dist/cli/managedDiagnostics.js +28 -0
  26. package/dist/cli/operatorWizard.js +1 -7
  27. package/dist/cli/roleOptionOrder.js +27 -0
  28. package/dist/cli/roleWizard.js +50 -14
  29. package/dist/cli/updateOrchestrator.js +1 -1
  30. package/dist/cli/updatePorts.js +3 -4
  31. package/dist/cli.js +245 -95
  32. package/dist/commands/agentCommands.js +72 -14
  33. package/dist/commands/capabilityCommands.js +9 -6
  34. package/dist/commands/configCommands.js +20 -20
  35. package/dist/commands/deliveryGuardPreflight.js +2 -2
  36. package/dist/commands/executionAuditCommands.js +24 -24
  37. package/dist/commands/globalRoleCommands.js +1 -1
  38. package/dist/commands/grantCommands.js +4 -4
  39. package/dist/commands/operatorCommands.js +34 -9
  40. package/dist/commands/projectCommands.js +4 -4
  41. package/dist/commands/resourcesCommands.js +2 -2
  42. package/dist/commands/roleConfiguration.js +25 -5
  43. package/dist/commands/roleRuntimeGuard.js +4 -5
  44. package/dist/commands/sessionCommands.js +3 -7
  45. package/dist/commands/taskActivationCommands.js +281 -0
  46. package/dist/commands/taskActor.js +28 -49
  47. package/dist/commands/taskCommands.js +1461 -720
  48. package/dist/commands/taskContextCommand.js +39 -583
  49. package/dist/commands/taskExecutionCommands.js +32 -32
  50. package/dist/commands/taskInputCommands.js +40 -104
  51. package/dist/commands/taskIntegrationCommands.js +3 -2
  52. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  53. package/dist/commands/taskNextActionCommand.js +8 -8
  54. package/dist/commands/taskOverviewCommand.js +33 -45
  55. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  56. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  57. package/dist/commands/telemetryCommands.js +36 -38
  58. package/dist/config/configCatalog.js +4 -4
  59. package/dist/config/yuiConfig.js +8 -8
  60. package/dist/context/contextSnapshot.js +10 -10
  61. package/dist/context/dispatchContext.js +11 -11
  62. package/dist/context/roleSessionContext.js +6 -3
  63. package/dist/context/{turnContextPack.js → runContextPack.js} +158 -81
  64. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  65. package/dist/context/sessionBootstrapManifest.js +21 -2
  66. package/dist/context/sourceRunContext.js +30 -0
  67. package/dist/context/taskContext.js +481 -0
  68. package/dist/context/wakeNotification.js +27 -27
  69. package/dist/controller/agentRuntimeObserver.js +21 -24
  70. package/dist/controller/capabilityBridge.js +17 -6
  71. package/dist/controller/clientRuntime.js +65 -92
  72. package/dist/controller/controller.js +120 -188
  73. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  74. package/dist/controller/jobControl.js +54 -85
  75. package/dist/controller/resourceInventory.js +8 -27
  76. package/dist/controller/resourceInventoryLinux.js +12 -13
  77. package/dist/controller/runtime.js +529 -479
  78. package/dist/controller/runtimeEventInbox.js +55 -25
  79. package/dist/controller/runtimeEventProcessor.js +22 -31
  80. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  81. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  82. package/dist/controller/runtimeObservationHook.js +14 -18
  83. package/dist/controller/sessionNotify.js +16 -24
  84. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  85. package/dist/controller/structuredProviderObservation.js +138 -99
  86. package/dist/coordination/workMailbox.js +3 -3
  87. package/dist/coordination/workMailboxQueue.js +36 -33
  88. package/dist/core/boundedRpc.js +8 -1
  89. package/dist/core/controllerClient.js +20 -1
  90. package/dist/core/controllerServer.js +4 -4
  91. package/dist/doctor/doctor.js +13 -2
  92. package/dist/domain/agentResultTransport.js +9 -9
  93. package/dist/execution/codexThreadNaming.js +2 -8
  94. package/dist/execution/executionHealth.js +51 -63
  95. package/dist/execution/reviewMainRun.js +137 -0
  96. package/dist/execution/workItemExecution.js +28 -29
  97. package/dist/execution/workItemExecutionProjection.js +99 -107
  98. package/dist/execution/workItemMainRun.js +141 -0
  99. package/dist/executor/agentAdapter.js +227 -20
  100. package/dist/executor/agentConfigurationCatalog.js +126 -4
  101. package/dist/executor/agentConfigurationProbe.js +162 -4
  102. package/dist/executor/agentExecutor.js +79 -78
  103. package/dist/executor/effectiveLaunch.js +105 -18
  104. package/dist/executor/executorRegistry.js +29 -44
  105. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  106. package/dist/executor/workspacePreflightClassification.js +16 -16
  107. package/dist/grant/capabilityGrant.js +6 -3
  108. package/dist/input/inputRequest.js +12 -10
  109. package/dist/integration/gitIntegrationService.js +4 -11
  110. package/dist/integration/integrationQueueService.js +4 -4
  111. package/dist/interaction/operatorPresentation.js +1 -1
  112. package/dist/kernel/builtinCapabilities.js +255 -12
  113. package/dist/kernel/capabilityRegistry.js +64 -18
  114. package/dist/kernel/instanceHost.js +12 -1
  115. package/dist/kernel/kernelPorts.js +2 -2
  116. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  117. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  118. package/dist/message/message.js +118 -6
  119. package/dist/message/messageContinuation.js +204 -0
  120. package/dist/observability/executionAudit.js +70 -72
  121. package/dist/observability/faultClassification.js +2 -2
  122. package/dist/observability/orchestrationMetrics.js +8 -8
  123. package/dist/operator/operatorSessionHistory.js +1 -7
  124. package/dist/output/agentConfigurationPresentation.js +8 -3
  125. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  126. package/dist/output/rolePresentation.js +54 -3
  127. package/dist/plugins/pluginChild.js +104 -0
  128. package/dist/plugins/pluginIntent.js +26 -0
  129. package/dist/plugins/pluginInterpreter.js +43 -0
  130. package/dist/plugins/pluginPackage.js +101 -0
  131. package/dist/plugins/pluginProcess.js +112 -0
  132. package/dist/plugins/pluginService.js +388 -0
  133. package/dist/profile/agentProfile.js +1 -1
  134. package/dist/repository/gitWorkspace.js +26 -4
  135. package/dist/repository/project.js +19 -4
  136. package/dist/repository/taskBaseFreshness.js +13 -13
  137. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  138. package/dist/repository/taskWorkspacePreparer.js +344 -83
  139. package/dist/resources/autoResourceGc.js +3 -3
  140. package/dist/resources/liveReferences.js +3 -3
  141. package/dist/resources/projectResource.js +75 -0
  142. package/dist/resources/projectResourceService.js +343 -0
  143. package/dist/resources/resourceDiscovery.js +6 -6
  144. package/dist/resources/resourceGc.js +1 -1
  145. package/dist/resources/resourceRegistrar.js +1 -1
  146. package/dist/resources/resourceTypes.js +1 -1
  147. package/dist/review/deltaRecheck.js +3 -3
  148. package/dist/review/reviewAcceptance.js +16 -16
  149. package/dist/review/reviewDecision.js +7 -7
  150. package/dist/review/reviewRound.js +21 -20
  151. package/dist/review/reviewerAvailability.js +2 -2
  152. package/dist/role/role.js +51 -7
  153. package/dist/role/taskRoleUpdate.js +30 -0
  154. package/dist/runtime/acpProtocol.js +425 -0
  155. package/dist/runtime/acpSession.js +731 -0
  156. package/dist/runtime/acpSessionConfiguration.js +260 -0
  157. package/dist/runtime/agentDriver.js +30 -11
  158. package/dist/runtime/agentEndpoint.js +278 -0
  159. package/dist/runtime/agentEndpointIdentity.js +86 -0
  160. package/dist/runtime/agentEndpointOwnership.js +239 -0
  161. package/dist/runtime/agentError.js +2 -10
  162. package/dist/runtime/agentHost.js +565 -314
  163. package/dist/runtime/agentRunConfiguration.js +258 -0
  164. package/dist/runtime/builtinAgentDrivers.js +134 -18
  165. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  166. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  167. package/dist/runtime/claude-process-owner +0 -0
  168. package/dist/runtime/codexAppServerRuntime.js +38 -30
  169. package/dist/runtime/codexInteractiveHost.js +41 -6
  170. package/dist/runtime/continuationManager.js +2 -6
  171. package/dist/runtime/executionEnvironment.js +30 -0
  172. package/dist/runtime/firstProgressAdvisory.js +11 -11
  173. package/dist/runtime/index.js +4 -3
  174. package/dist/runtime/jsonLineChannel.js +109 -0
  175. package/dist/runtime/launchBroker.js +91 -16
  176. package/dist/runtime/launchDiagnostics.js +2 -2
  177. package/dist/runtime/lifecycleReservation.js +10 -18
  178. package/dist/runtime/managedCaller.js +61 -17
  179. package/dist/runtime/nativeSessionControl.js +102 -0
  180. package/dist/runtime/ports.js +6 -21
  181. package/dist/runtime/processExitObservation.js +8 -7
  182. package/dist/runtime/promptEnvelope.js +17 -6
  183. package/dist/runtime/providerContinuation.js +3 -9
  184. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  185. package/dist/runtime/providerControl.js +2 -7
  186. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  187. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  188. package/dist/runtime/runtimeBinding.js +0 -1
  189. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  190. package/dist/runtime/runtimeDeadlines.js +9 -0
  191. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  192. package/dist/runtime/runtimeObservation.js +29 -65
  193. package/dist/runtime/runtimeProjection.js +43 -51
  194. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  195. package/dist/runtime/sessionLaunchRequest.js +3 -7
  196. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  197. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  198. package/dist/runtime/sessionReconciliation.js +4 -8
  199. package/dist/runtime/sessionTerminationGuard.js +70 -259
  200. package/dist/runtime/sessionTokenMetrics.js +5 -16
  201. package/dist/runtime/structuredProviderHost.js +237 -117
  202. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  203. package/dist/runtime/tmuxAdapters.js +39 -86
  204. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  205. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  206. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  207. package/dist/scheduler/ports.js +80 -9
  208. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  209. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  210. package/dist/scheduler/taskExecutionProjection.js +120 -124
  211. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  212. package/dist/scheduler/taskWake.js +11 -4
  213. package/dist/scheduler/wakeReason.js +9 -1
  214. package/dist/setup/setupCommand.js +3 -7
  215. package/dist/storage/migrations/agentRunContract.js +159 -0
  216. package/dist/storage/migrations/artifactsToGit.js +338 -0
  217. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  218. package/dist/storage/migrations/submitIntent.js +126 -0
  219. package/dist/storage/sqliteSchema.js +467 -7
  220. package/dist/storage/sqliteStore.js +355 -220
  221. package/dist/storage/storageVersions.js +1 -1
  222. package/dist/storage/storeRpc.js +10 -5
  223. package/dist/storage/taskStore.js +13 -11
  224. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  225. package/dist/surface/surfaceContributions.js +102 -0
  226. package/dist/task/completionReadiness.js +32 -6
  227. package/dist/task/deliveryGuard.js +16 -16
  228. package/dist/task/draftPlan.js +72 -12
  229. package/dist/task/nextAction.js +144 -128
  230. package/dist/task/remoteDelivery.js +6 -6
  231. package/dist/task/task.js +184 -18
  232. package/dist/task/taskActivation.js +327 -0
  233. package/dist/task/taskActivationService.js +408 -0
  234. package/dist/task/taskRecordReference.js +5 -4
  235. package/dist/task/taskRecordRetirement.js +1 -1
  236. package/dist/task/taskSubmission.js +236 -0
  237. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  238. package/dist/telemetry/telemetryConfig.js +14 -14
  239. package/dist/telemetry/telemetryWiring.js +2 -2
  240. package/dist/web/assets/assetManifest.js +2 -0
  241. package/dist/web/assets/client/app.js +121 -20
  242. package/dist/web/assets/client/components.js +87 -54
  243. package/dist/web/assets/client/i18n.js +83 -41
  244. package/dist/web/assets/client/markdown.js +1 -1
  245. package/dist/web/assets/client/taskSurface.js +442 -0
  246. package/dist/web/assets/client/view.js +49 -44
  247. package/dist/web/assets/shell.js +1 -1
  248. package/dist/web/assets/styles/cards.js +22 -4
  249. package/dist/web/controllerWeb.js +60 -0
  250. package/dist/web/webMutation.js +28 -0
  251. package/dist/web/webServer.js +133 -8
  252. package/dist/web/webSnapshot.js +81 -74
  253. package/dist/web/webTaskSurface.js +64 -0
  254. package/dist/workItem/dependencyGate.js +1 -1
  255. package/dist/workItem/workItem.js +84 -48
  256. package/dist/workspace/workItemChangeSetManager.js +16 -9
  257. package/docs/agent-result-consumption.md +96 -0
  258. package/docs/agent-result-consumption.zh-CN.md +81 -0
  259. package/docs/agent-runtime-drivers.md +93 -0
  260. package/docs/agent-runtime-drivers.zh-CN.md +77 -0
  261. package/docs/architecture/README.md +50 -0
  262. package/docs/architecture/README.zh-CN.md +43 -0
  263. package/docs/architecture/capabilities-and-resources.md +118 -0
  264. package/docs/architecture/capabilities-and-resources.zh-CN.md +83 -0
  265. package/docs/managed-turn-and-session-runtime.md +224 -0
  266. package/docs/managed-turn-and-session-runtime.zh-CN.md +180 -0
  267. package/docs/observability/README.md +83 -0
  268. package/docs/observability/README.zh-CN.md +71 -0
  269. package/docs/plugin-sdk.md +393 -0
  270. package/docs/plugin-sdk.zh-CN.md +293 -0
  271. package/docs/provider-runtime.md +165 -0
  272. package/docs/provider-runtime.zh-CN.md +132 -0
  273. package/docs/release-workflow.md +305 -0
  274. package/docs/release-workflow.zh-CN.md +237 -0
  275. package/docs/roles-and-configuration.md +115 -0
  276. package/docs/roles-and-configuration.zh-CN.md +96 -0
  277. package/docs/sqlite-control-plane-design.md +78 -0
  278. package/docs/sqlite-control-plane-design.zh-CN.md +62 -0
  279. package/docs/task-dag-semantics.md +80 -0
  280. package/docs/task-dag-semantics.zh-CN.md +59 -0
  281. package/docs/task-delivery.md +105 -0
  282. package/docs/task-delivery.zh-CN.md +82 -0
  283. package/docs/task-local-identity.md +8 -6
  284. package/docs/task-local-identity.zh-CN.md +58 -0
  285. package/docs/testing/verification-levels.md +88 -0
  286. package/docs/testing/verification-levels.zh-CN.md +69 -0
  287. package/i18n/README.zh-CN.md +270 -722
  288. package/package.json +3 -2
  289. package/skills/yui-leader/SKILL.md +88 -304
  290. package/skills/yui-leader/references/execution.md +303 -0
  291. package/skills/yui-leader/references/integration.md +39 -0
  292. package/skills/yui-leader/references/planning.md +109 -0
  293. package/skills/yui-leader/references/replicated-execution.md +42 -0
  294. package/skills/yui-leader/references/task-plugins.md +37 -0
  295. package/skills/yui-operator/SKILL.md +46 -62
  296. package/skills/yui-reviewer/SKILL.md +35 -36
  297. package/skills/yui-runtime/SKILL.md +88 -24
  298. package/skills/yui-runtime/references/publication.md +22 -0
  299. package/skills/yui-runtime/references/recovery.md +64 -0
  300. package/skills/yui-worker/SKILL.md +37 -39
  301. package/dist/cli/roleOptionCatalog.js +0 -68
  302. package/dist/context/sourceTurnContext.js +0 -30
  303. package/dist/execution/reviewMainTurn.js +0 -161
  304. package/dist/execution/workItemMainTurn.js +0 -164
  305. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  306. package/dist/runtime/preallocatedNativeSession.js +0 -13
  307. package/dist/runtime/runtimeStopReceipt.js +0 -42
  308. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -1,15 +1,17 @@
1
1
  import { operationalTaskRecords } from "../task/taskRecordRetirement.js";
2
2
  import { TASK_COMPLETION_PUBLISHED_TREE_AUTHORIZED_EVENT } from "../task/publicationReference.js";
3
- import { TURN_INPUT_MAX_DELTAS } from "./turnInputContract.js";
3
+ import { RUN_INPUT_MAX_DELTAS } from "./runInputContract.js";
4
4
  import { assertWorkItemDependenciesCompleted } from "../workItem/dependencyGate.js";
5
- import { workItemExecutionGroupById } from "../workItem/workItem.js";
5
+ import { governingWorkItemCandidate, workItemExecutionGroupById } from "../workItem/workItem.js";
6
+ import { formatGitArtifactRef, validateGitArtifactRef } from "../artifacts/gitArtifactRef.js";
7
+ import { managedWorkspaceKey } from "../worktree/managedWorkspace.js";
6
8
  import { contextContentDigest, contextSnapshotRef, createContextSnapshot, validateContextSnapshot } from "./contextSnapshot.js";
7
- import { sourceTurnContextValue } from "./sourceTurnContext.js";
8
- export const TURN_CONTEXT_PACK_SCHEMA_VERSION = 1;
9
- export const TURN_CONTEXT_PACK_MAX_REFS = 256;
10
- export const TURN_CONTEXT_PACK_MAX_BYTES = 8 * 1024 * 1024;
11
- export const TURN_CONTEXT_EXPAND_MAX_BYTES = 4 * 1024 * 1024;
12
- export function freezeTurnContextSnapshot(store, run, now, frozenBy = "controller", baselineRef) {
9
+ import { MAX_SYNTHESIS_SOURCE_RUNS, sourceRunContextValue } from "./sourceRunContext.js";
10
+ export const RUN_CONTEXT_PACK_SCHEMA_VERSION = 1;
11
+ export const RUN_CONTEXT_PACK_MAX_REFS = 256;
12
+ export const RUN_CONTEXT_PACK_MAX_BYTES = 8 * 1024 * 1024;
13
+ export const RUN_CONTEXT_EXPAND_MAX_BYTES = 4 * 1024 * 1024;
14
+ export function freezeRunContextSnapshot(store, run, now, frozenBy = "controller", baselineRef, sourceRunIds) {
13
15
  if (baselineRef !== undefined) {
14
16
  const baseline = store.getContextSnapshot(run.taskId, baselineRef.id);
15
17
  if (baseline === null
@@ -20,12 +22,12 @@ export function freezeTurnContextSnapshot(store, run, now, frozenBy = "controlle
20
22
  || baseline.scope !== "stage"
21
23
  || baselineRef.scope !== baseline.scope
22
24
  || baseline.scopeRef !== baselineRef.scopeRef) {
23
- throw new Error(`Turn Context baseline is missing or drifted: ${baselineRef.id}.`);
25
+ throw new Error(`AgentRun Context baseline is missing or drifted: ${baselineRef.id}.`);
24
26
  }
25
27
  validateContextSnapshot(baseline);
26
28
  const overlays = [
27
- ...collectTurnContextOverlays(store, run),
28
- ...collectSourceTurnContext(store, run)
29
+ ...collectRunContextOverlays(store, run),
30
+ ...collectSourceRunContext(store, run, sourceRunIds)
29
31
  ];
30
32
  const resources = [...new Map([...baseline.resources, ...overlays].map((entry) => [
31
33
  contextRefIdentity(entry.ref),
@@ -82,7 +84,7 @@ export function freezeTurnContextSnapshot(store, run, now, frozenBy = "controlle
82
84
  }
83
85
  /**
84
86
  * Freeze the shared, role-neutral ContextSnapshot anchored by one WorkItem
85
- * ExecutionAssignment. Turn snapshots remain role-specific; this record is
87
+ * ExecutionAssignment. AgentRun snapshots remain role-specific; this record is
86
88
  * the durable Assignment baseline and freezes the current WorkItem facts so
87
89
  * the Group never depends on ambient latest state.
88
90
  */
@@ -97,17 +99,19 @@ export function freezeWorkItemExecutionAssignmentContextSnapshot(store, input, n
97
99
  materialize("L2", "task", task.id, task),
98
100
  materialize("L3", "work-item", workItem.id, workItem)
99
101
  ];
102
+ materialized.push(...candidateArtifacts(task.id, workItem.candidates));
100
103
  assertWorkItemDependenciesCompleted(store, workItem);
101
104
  for (const dependencyId of workItem.dependsOn) {
102
105
  const dependency = store.getWorkItem(task.id, dependencyId);
103
106
  if (dependency === null)
104
107
  throw new Error(`WorkItem dependency disappeared: ${dependencyId}.`);
105
108
  materialized.push(materialize("L3", "accepted-work-item", dependency.id, dependency));
109
+ materialized.push(...candidateArtifacts(task.id, dependency.candidates));
106
110
  }
107
111
  for (const binding of task.projectBindings) {
108
112
  const project = store.getProject(binding.projectId);
109
113
  if (project === null)
110
- throw new Error(`Turn Project not found: ${binding.projectId}.`);
114
+ throw new Error(`AgentRun Project not found: ${binding.projectId}.`);
111
115
  const { knowledge, ...projectPolicy } = project;
112
116
  materialized.push(materialize("L1", "project-policy", project.id, projectPolicy));
113
117
  for (const entry of knowledge.filter(({ status }) => status === "active")) {
@@ -200,10 +204,10 @@ export function contextSnapshotDeltaRefIds(store, snapshot) {
200
204
  || before.store !== ref.store
201
205
  || before.layer !== ref.layer;
202
206
  }).map(({ refId }) => refId);
203
- return Object.freeze([...new Set(changed)].sort().slice(0, TURN_INPUT_MAX_DELTAS));
207
+ return Object.freeze([...new Set(changed)].sort().slice(0, RUN_INPUT_MAX_DELTAS));
204
208
  }
205
- export function buildTurnContextPack(store, taskId, turnId) {
206
- const run = requireExactTurn(store, taskId, turnId);
209
+ export function buildRunContextPack(store, taskId, runId) {
210
+ const run = requireExactRun(store, taskId, runId);
207
211
  const current = collectAuthorizedContext(store, run);
208
212
  let pointers = current.map(({ ref }) => ref);
209
213
  let snapshotRef;
@@ -211,16 +215,16 @@ export function buildTurnContextPack(store, taskId, turnId) {
211
215
  const expected = run.inputs[0].input.contextSnapshotRef;
212
216
  const snapshot = store.getContextSnapshot(taskId, expected.id);
213
217
  if (snapshot === null)
214
- throw new Error(`Turn Context Snapshot is missing: ${expected.id}.`);
218
+ throw new Error(`AgentRun Context Snapshot is missing: ${expected.id}.`);
215
219
  validateContextSnapshot(snapshot);
216
220
  if (snapshot.digest !== expected.digest || snapshot.taskId !== taskId) {
217
- throw new Error(`Turn Context Snapshot identity drifted: ${expected.id}.`);
221
+ throw new Error(`AgentRun Context Snapshot identity drifted: ${expected.id}.`);
218
222
  }
219
223
  pointers = snapshot.refs;
220
224
  snapshotRef = contextSnapshotRef(snapshot);
221
225
  }
222
- if (pointers.length > TURN_CONTEXT_PACK_MAX_REFS) {
223
- throw new Error(`Turn Context exceeds ${TURN_CONTEXT_PACK_MAX_REFS} authorized refs.`);
226
+ if (pointers.length > RUN_CONTEXT_PACK_MAX_REFS) {
227
+ throw new Error(`AgentRun Context exceeds ${RUN_CONTEXT_PACK_MAX_REFS} authorized refs.`);
224
228
  }
225
229
  const view = contextView(run);
226
230
  const writableProjectIds = writableProjects(store, run, view);
@@ -231,10 +235,10 @@ export function buildTurnContextPack(store, taskId, turnId) {
231
235
  digest: ref.digest
232
236
  }));
233
237
  const body = {
234
- schemaVersion: TURN_CONTEXT_PACK_SCHEMA_VERSION,
238
+ schemaVersion: RUN_CONTEXT_PACK_SCHEMA_VERSION,
235
239
  identity: Object.freeze({
236
240
  taskId,
237
- turnId: turnId,
241
+ runId: runId,
238
242
  roleName: run.roleName,
239
243
  purpose: run.purpose,
240
244
  agentId: run.effective.agentId,
@@ -248,21 +252,21 @@ export function buildTurnContextPack(store, taskId, turnId) {
248
252
  summaries,
249
253
  deltas: pointers.filter((ref) => run.inputs[0].input.deltaRefIds.includes(ref.refId)),
250
254
  completion: Object.freeze({
251
- allowedActions: completionActions(view),
252
- exactTurnRef: `${taskId}/${turnId}`
255
+ allowedActions: completionActions(view, run.effective.executionAuthority),
256
+ exactRunRef: `${taskId}/${runId}`
253
257
  })
254
258
  };
255
259
  const digest = contextContentDigest(body);
256
260
  const preliminaryBytes = Buffer.byteLength(JSON.stringify({ ...body, digest }), "utf8");
257
- if (preliminaryBytes > TURN_CONTEXT_PACK_MAX_BYTES) {
258
- throw new Error(`Turn Context Pack exceeds ${TURN_CONTEXT_PACK_MAX_BYTES} bytes.`);
261
+ if (preliminaryBytes > RUN_CONTEXT_PACK_MAX_BYTES) {
262
+ throw new Error(`AgentRun Context Pack exceeds ${RUN_CONTEXT_PACK_MAX_BYTES} bytes.`);
259
263
  }
260
264
  const pack = Object.freeze({
261
265
  ...body,
262
266
  budget: Object.freeze({
263
- maxRefs: TURN_CONTEXT_PACK_MAX_REFS,
267
+ maxRefs: RUN_CONTEXT_PACK_MAX_REFS,
264
268
  returnedRefs: pointers.length,
265
- maxBytes: TURN_CONTEXT_PACK_MAX_BYTES,
269
+ maxBytes: RUN_CONTEXT_PACK_MAX_BYTES,
266
270
  returnedBytes: preliminaryBytes,
267
271
  truncated: false
268
272
  }),
@@ -273,14 +277,14 @@ export function buildTurnContextPack(store, taskId, turnId) {
273
277
  }
274
278
  /** Reads the Task's current in-flight execution, outside the frozen contract. */
275
279
  function readLiveTaskState(store, taskId) {
276
- const activeTurns = store.listTurns(taskId)
277
- .filter((turn) => turn.status === "active")
278
- .map((turn) => Object.freeze({
279
- turnId: turn.id,
280
- roleName: turn.roleName,
281
- purpose: turn.purpose,
282
- ...(turn.workItemId === undefined ? {} : { workItemId: turn.workItemId }),
283
- ...(turn.reviewRoundId === undefined ? {} : { reviewRoundId: turn.reviewRoundId })
280
+ const activeRuns = store.listRuns(taskId)
281
+ .filter((run) => run.status === "active")
282
+ .map((run) => Object.freeze({
283
+ runId: run.id,
284
+ roleName: run.roleName,
285
+ purpose: run.purpose,
286
+ ...(run.workItemId === undefined ? {} : { workItemId: run.workItemId }),
287
+ ...(run.reviewRoundId === undefined ? {} : { reviewRoundId: run.reviewRoundId })
284
288
  }));
285
289
  const activeTaskReviews = store.listReviewRounds(taskId)
286
290
  .filter((round) => ((round.scope ?? "work-item") === "task"
@@ -291,28 +295,28 @@ function readLiveTaskState(store, taskId) {
291
295
  status: round.status
292
296
  }));
293
297
  return Object.freeze({
294
- activeTurns: Object.freeze(activeTurns),
298
+ activeRuns: Object.freeze(activeRuns),
295
299
  activeTaskReviews: Object.freeze(activeTaskReviews)
296
300
  });
297
301
  }
298
- export function expandTurnContextRef(store, taskId, turnId, refId, refStore) {
299
- const pack = buildTurnContextPack(store, taskId, turnId);
302
+ export function expandRunContextRef(store, taskId, runId, refId, refStore) {
303
+ const pack = buildRunContextPack(store, taskId, runId);
300
304
  const authorized = pack.pointers.filter((ref) => (ref.refId === refId && (refStore === undefined || ref.store === refStore)));
301
305
  const selector = refStore === undefined ? refId : `${refStore}/${refId}`;
302
306
  if (authorized.length !== 1) {
303
- throw new Error(`Turn Context ref is not uniquely authorized: ${selector}.`);
307
+ throw new Error(`AgentRun Context ref is not uniquely authorized: ${selector}.`);
304
308
  }
305
- const run = requireExactTurn(store, taskId, turnId);
309
+ const run = requireExactRun(store, taskId, runId);
306
310
  const snapshotRef = run.inputs[0].input.contextSnapshotRef;
307
311
  const materialized = snapshotRef === undefined
308
312
  ? collectAuthorizedContext(store, run).find(({ ref }) => (contextRefIdentity(ref) === contextRefIdentity(authorized[0])))
309
313
  : store.getContextSnapshot(taskId, snapshotRef.id)?.resources.find(({ ref }) => (contextRefIdentity(ref) === contextRefIdentity(authorized[0])));
310
314
  if (materialized === undefined || materialized.ref.digest !== authorized[0].digest) {
311
- throw new Error(`Turn Context ref is unavailable or drifted: ${selector}.`);
315
+ throw new Error(`AgentRun Context ref is unavailable or drifted: ${selector}.`);
312
316
  }
313
317
  const bytes = Buffer.byteLength(JSON.stringify(materialized.value), "utf8");
314
- if (bytes > TURN_CONTEXT_EXPAND_MAX_BYTES) {
315
- throw new Error(`Turn Context expansion exceeds ${TURN_CONTEXT_EXPAND_MAX_BYTES} bytes.`);
318
+ if (bytes > RUN_CONTEXT_EXPAND_MAX_BYTES) {
319
+ throw new Error(`AgentRun Context expansion exceeds ${RUN_CONTEXT_EXPAND_MAX_BYTES} bytes.`);
316
320
  }
317
321
  return Object.freeze({
318
322
  ref: materialized.ref,
@@ -320,13 +324,13 @@ export function expandTurnContextRef(store, taskId, turnId, refId, refStore) {
320
324
  digest: contextContentDigest({ ref: materialized.ref, value: materialized.value })
321
325
  });
322
326
  }
323
- /** Fail-closed delta cursor resolution for one immutable Turn lineage. */
324
- export function buildTurnContextDelta(store, taskId, turnId, after) {
325
- const pack = buildTurnContextPack(store, taskId, turnId);
327
+ /** Fail-closed delta cursor resolution for one immutable AgentRun lineage. */
328
+ export function buildRunContextDelta(store, taskId, runId, after) {
329
+ const pack = buildRunContextPack(store, taskId, runId);
326
330
  if (after === pack.digest || after === pack.snapshot?.digest) {
327
331
  return Object.freeze({ schemaVersion: 1, after, cursor: pack.digest, refs: [] });
328
332
  }
329
- const run = requireExactTurn(store, taskId, turnId);
333
+ const run = requireExactRun(store, taskId, runId);
330
334
  const snapshotRef = run.inputs[0].input.contextSnapshotRef;
331
335
  const snapshot = snapshotRef === undefined
332
336
  ? null
@@ -334,7 +338,7 @@ export function buildTurnContextDelta(store, taskId, turnId, after) {
334
338
  const parentDigest = snapshot?.parentRef?.digest;
335
339
  if (!((parentDigest !== undefined && after === parentDigest)
336
340
  || (parentDigest === undefined && after === "none"))) {
337
- throw new Error("Turn Context delta cursor is outside the frozen Snapshot lineage.");
341
+ throw new Error("AgentRun Context delta cursor is outside the frozen Snapshot lineage.");
338
342
  }
339
343
  return Object.freeze({
340
344
  schemaVersion: 1,
@@ -343,10 +347,10 @@ export function buildTurnContextDelta(store, taskId, turnId, after) {
343
347
  refs: pack.deltas
344
348
  });
345
349
  }
346
- function requireExactTurn(store, taskId, turnId) {
347
- const run = store.getTurn(taskId, turnId);
348
- if (run === null || run.taskId !== taskId || run.id !== turnId) {
349
- throw new Error(`Turn not found: ${taskId}/${turnId}.`);
350
+ function requireExactRun(store, taskId, runId) {
351
+ const run = store.getRun(taskId, runId);
352
+ if (run === null || run.taskId !== taskId || run.id !== runId) {
353
+ throw new Error(`AgentRun not found: ${taskId}/${runId}.`);
350
354
  }
351
355
  return run;
352
356
  }
@@ -360,13 +364,14 @@ function collectAuthorizedContext(store, run) {
360
364
  if (brief !== null && view === "leader") {
361
365
  result.push(materialize("L2", "task-brief", task.id, brief));
362
366
  }
363
- result.push(...collectTurnContextOverlays(store, run));
364
- result.push(...collectSourceTurnContext(store, run));
367
+ result.push(...collectRunContextOverlays(store, run));
368
+ result.push(...collectSourceRunContext(store, run));
365
369
  if (run.workItemId !== undefined) {
366
370
  const item = store.getWorkItem(task.id, run.workItemId);
367
371
  if (item === null)
368
- throw new Error(`Turn WorkItem not found: ${run.workItemId}.`);
372
+ throw new Error(`AgentRun WorkItem not found: ${run.workItemId}.`);
369
373
  result.push(materialize("L3", "work-item", item.id, item));
374
+ result.push(...candidateArtifacts(task.id, item.candidates));
370
375
  if (view === "worker") {
371
376
  assertWorkItemDependenciesCompleted(store, item);
372
377
  for (const dependencyId of item.dependsOn) {
@@ -374,35 +379,45 @@ function collectAuthorizedContext(store, run) {
374
379
  if (dependency === null)
375
380
  throw new Error(`WorkItem dependency disappeared: ${dependencyId}.`);
376
381
  result.push(materialize("L3", "accepted-work-item", dependency.id, dependency));
382
+ result.push(...candidateArtifacts(task.id, dependency.candidates));
377
383
  }
378
384
  }
379
385
  }
380
386
  if (run.reviewRoundId !== undefined) {
381
387
  const round = store.getReviewRound(task.id, run.reviewRoundId);
382
388
  if (round === null)
383
- throw new Error(`Turn ReviewRound not found: ${run.reviewRoundId}.`);
389
+ throw new Error(`AgentRun ReviewRound not found: ${run.reviewRoundId}.`);
384
390
  result.push(materialize("L3", "review-round", round.id, round));
391
+ if (round.scope === "task") {
392
+ for (const item of store.listWorkItems(task.id).filter(({ status }) => status !== "retired")) {
393
+ const candidate = governingWorkItemCandidate(item);
394
+ if (candidate === undefined)
395
+ continue;
396
+ result.push(materialize("L3", "candidate", `${item.id}/${candidate.id}`, candidate));
397
+ result.push(...candidateArtifacts(task.id, [candidate]));
398
+ }
399
+ }
385
400
  if (round.deltaRecheck !== undefined) {
386
401
  const previous = store.getReviewRound(task.id, round.deltaRecheck.previousReviewRoundId);
387
- const previousTurn = previous?.reviewerTurnId === undefined
402
+ const previousRun = previous?.reviewerRunId === undefined
388
403
  ? null
389
- : store.getTurn(task.id, previous.reviewerTurnId);
404
+ : store.getRun(task.id, previous.reviewerRunId);
390
405
  if (previous === null
391
406
  || previous === undefined
392
407
  || previous.status !== "completed"
393
- || previousTurn === null
394
- || previousTurn.status !== "completed"
395
- || previousTurn.result === undefined) {
408
+ || previousRun === null
409
+ || previousRun.status !== "completed"
410
+ || previousRun.result === undefined) {
396
411
  throw new Error(`Delta recheck source Review result is unavailable: ${round.deltaRecheck.previousReviewRoundId}.`);
397
412
  }
398
413
  result.push(materialize("L3", "review-round", previous.id, previous));
399
- result.push(materialize("L4", "source-turn", previousTurn.id, sourceTurnContextValue(previousTurn)));
414
+ result.push(materialize("L4", "source-run", previousRun.id, sourceRunContextValue(previousRun)));
400
415
  }
401
416
  }
402
417
  for (const binding of task.projectBindings) {
403
418
  const project = store.getProject(binding.projectId);
404
419
  if (project === null)
405
- throw new Error(`Turn Project not found: ${binding.projectId}.`);
420
+ throw new Error(`AgentRun Project not found: ${binding.projectId}.`);
406
421
  const { knowledge, ...projectPolicy } = project;
407
422
  result.push(materialize("L1", "project-policy", project.id, projectPolicy));
408
423
  for (const entry of knowledge.filter(({ status }) => status === "active")) {
@@ -410,6 +425,21 @@ function collectAuthorizedContext(store, run) {
410
425
  }
411
426
  }
412
427
  if (view === "leader") {
428
+ // File artifacts are NOT enumerated into the synchronous context pack: the
429
+ // core cursor does not cover file edits, and an ambient directory listing
430
+ // here would be exactly the forbidden update-time mirror (§3.7). The Leader
431
+ // reads current artifacts on demand via the async `artifact.list` /
432
+ // `artifact.read` capabilities; frozen Candidate artifacts still enter the
433
+ // pack as commit-pinned pointers through candidateArtifacts().
434
+ for (const preparation of store.listEnvironmentPreparations(task.id)) {
435
+ result.push(materialize("L3", "environment-preparation", preparation.id, preparation));
436
+ }
437
+ for (const workspace of store.listManagedWorkspaces(task.id)) {
438
+ result.push(materialize("L3", "managed-workspace", managedWorkspaceKey(workspace.owner), workspace));
439
+ }
440
+ for (const changeSet of store.listChangeSets(task.id)) {
441
+ result.push(materialize("L3", "change-set", changeSet.id, changeSet));
442
+ }
413
443
  const events = store.listEvents(task.id);
414
444
  for (const item of store.listWorkItems(task.id).filter(({ status }) => status !== "retired")) {
415
445
  result.push(materialize("L3", "work-item", item.id, item));
@@ -423,8 +453,8 @@ function collectAuthorizedContext(store, run) {
423
453
  for (const round of store.listReviewRounds(task.id).slice(-16)) {
424
454
  result.push(materialize("L3", "review-round", round.id, round));
425
455
  }
426
- for (const turn of operationalTaskRecords(store.listTurns(task.id), events, "turn").slice(-24)) {
427
- result.push(materialize("L4", "turn", turn.id, turn));
456
+ for (const run of operationalTaskRecords(store.listRuns(task.id), events, "run").slice(-24)) {
457
+ result.push(materialize("L4", "run", run.id, run));
428
458
  }
429
459
  for (const message of operationalTaskRecords(store.listMessages(task.id), events, "message").slice(-16)) {
430
460
  result.push(materialize("L4", "task-message", message.id, message));
@@ -448,11 +478,33 @@ function collectAuthorizedContext(store, run) {
448
478
  const unique = new Map(result.map((entry) => [contextRefIdentity(entry.ref), entry]));
449
479
  return [...unique.values()].sort((left, right) => (contextRefIdentity(left.ref).localeCompare(contextRefIdentity(right.ref))));
450
480
  }
481
+ /** Only artifacts attached to already-authorized candidates enter a bounded
482
+ * Worker/Reviewer snapshot. Each is a commit-pinned pointer: the commit
483
+ * self-certifies the frozen bytes, so the pointer is carried as pure data with
484
+ * NO build-time Git read. The bytes are resolved lazily on the async expand
485
+ * path (`artifact.read` at the pinned commit); the pointer survives cleanup of
486
+ * the producing workspace and Session. */
487
+ function candidateArtifacts(taskId, candidates) {
488
+ return candidates.flatMap((candidate) => (candidate.artifactRefs ?? []).map((ref) => {
489
+ const pinned = validateGitArtifactRef(ref);
490
+ if (pinned.taskId !== taskId) {
491
+ throw new Error(`Candidate Artifact belongs to another Task: ${pinned.taskId}.`);
492
+ }
493
+ // The refId is the self-certifying string form; the value is the pure
494
+ // pointer, never the bytes. inspectValue reconstructs the same pointer.
495
+ return materialize("L3", "artifact", formatGitArtifactRef(pinned), {
496
+ taskId: pinned.taskId,
497
+ commit: pinned.commit,
498
+ relativePath: pinned.relativePath,
499
+ ...(pinned.digest === undefined ? {} : { digest: pinned.digest })
500
+ });
501
+ }));
502
+ }
451
503
  /** Lane-specific context that may be layered over an immutable stage base. */
452
- function collectTurnContextOverlays(store, run) {
504
+ function collectRunContextOverlays(store, run) {
453
505
  const role = store.getRole(run.taskId, run.roleName);
454
506
  if (role === null)
455
- throw new Error(`Turn Role not found: ${run.taskId}/${run.roleName}.`);
507
+ throw new Error(`AgentRun Role not found: ${run.taskId}/${run.roleName}.`);
456
508
  return [
457
509
  materialize("L1", "role-profile", role.name, {
458
510
  name: role.name,
@@ -469,9 +521,14 @@ function collectTurnContextOverlays(store, run) {
469
521
  : [])
470
522
  ];
471
523
  }
472
- function collectSourceTurnContext(store, run) {
524
+ function collectSourceRunContext(store, run, sourceRunIds) {
473
525
  if (run.sourceExecutionGroupId === undefined)
474
526
  return [];
527
+ if (sourceRunIds === undefined || sourceRunIds.length === 0
528
+ || sourceRunIds.length > MAX_SYNTHESIS_SOURCE_RUNS
529
+ || new Set(sourceRunIds).size !== sourceRunIds.length) {
530
+ throw new Error("Synthesis requires explicit, distinct source AgentRun references.");
531
+ }
475
532
  const group = run.purpose === "execution"
476
533
  ? (() => {
477
534
  if (run.workItemId === undefined) {
@@ -479,7 +536,7 @@ function collectSourceTurnContext(store, run) {
479
536
  }
480
537
  const item = store.getWorkItem(run.taskId, run.workItemId);
481
538
  if (item === null)
482
- throw new Error(`Turn WorkItem not found: ${run.workItemId}.`);
539
+ throw new Error(`AgentRun WorkItem not found: ${run.workItemId}.`);
483
540
  return workItemExecutionGroupById(item, run.sourceExecutionGroupId);
484
541
  })()
485
542
  : (() => {
@@ -488,7 +545,7 @@ function collectSourceTurnContext(store, run) {
488
545
  }
489
546
  const round = store.getReviewRound(run.taskId, run.reviewRoundId);
490
547
  if (round === null)
491
- throw new Error(`Turn ReviewRound not found: ${run.reviewRoundId}.`);
548
+ throw new Error(`AgentRun ReviewRound not found: ${run.reviewRoundId}.`);
492
549
  return round.executionGroup?.id === run.sourceExecutionGroupId
493
550
  ? round.executionGroup
494
551
  : undefined;
@@ -496,23 +553,39 @@ function collectSourceTurnContext(store, run) {
496
553
  if (group === undefined) {
497
554
  throw new Error(`Source ExecutionGroup not found: ${run.sourceExecutionGroupId}.`);
498
555
  }
499
- return [...group.lanes]
500
- .sort((left, right) => left.ordinal - right.ordinal || left.id.localeCompare(right.id))
501
- .flatMap((lane) => {
502
- if (lane.disposition !== "succeeded" || lane.successfulTurnId === undefined)
503
- return [];
504
- const source = store.getTurn(run.taskId, lane.successfulTurnId);
556
+ return sourceRunIds.map((runId) => {
557
+ const source = store.getRun(run.taskId, runId);
558
+ const lane = group.lanes.find(({ id }) => id === source?.executionLaneId);
505
559
  if (source === null
506
- || source.status !== "completed"
560
+ || lane === undefined
561
+ || !["completed", "failed"].includes(source.status)
507
562
  || source.result === undefined
563
+ || source.purpose !== run.purpose
564
+ || source.workItemId !== run.workItemId
565
+ || source.reviewRoundId !== run.reviewRoundId
508
566
  || source.executionGroupId !== group.id
509
567
  || source.executionLaneId !== lane.id
510
568
  || source.roleName !== lane.roleName) {
511
- throw new Error(`Successful source Turn is missing or drifted: ${group.id}/${lane.id}.`);
569
+ throw new Error(`Selected source AgentRun is missing or drifted: ${group.id}/${runId}.`);
512
570
  }
513
- return [materialize("L4", "source-turn", source.id, sourceTurnContextValue(source))];
571
+ return materialize("L4", "source-run", source.id, sourceRunContextValue(source));
514
572
  });
515
573
  }
574
+ /** The frozen refs, not the Group's changing lane state, define provenance. */
575
+ export function synthesisSourceRunIds(store, run) {
576
+ const ref = run.inputs[0].input.contextSnapshotRef;
577
+ if (ref === undefined)
578
+ throw new Error(`Synthesis AgentRun has no Context Snapshot: ${run.id}.`);
579
+ const snapshot = store.getContextSnapshot(run.taskId, ref.id);
580
+ if (snapshot === null || snapshot.digest !== ref.digest
581
+ || snapshot.sequence !== ref.sequence || snapshot.scope !== ref.scope
582
+ || snapshot.scopeRef !== ref.scopeRef || snapshot.taskId !== run.taskId) {
583
+ throw new Error(`Synthesis Context Snapshot is missing or drifted: ${ref.id}.`);
584
+ }
585
+ validateContextSnapshot(snapshot);
586
+ return snapshot.resources.filter(({ ref: entry, value }) => (entry.store === "source-run"
587
+ && value.executionGroupId === run.sourceExecutionGroupId)).map(({ ref: entry }) => entry.refId);
588
+ }
516
589
  function materialize(layer, store, refId, value) {
517
590
  const digest = contextContentDigest(value);
518
591
  const record = value;
@@ -547,6 +620,8 @@ function contextView(run) {
547
620
  return "worker";
548
621
  }
549
622
  function writableProjects(store, run, view) {
623
+ if (run.effective.executionAuthority === "planning")
624
+ return Object.freeze([]);
550
625
  if (view === "leader")
551
626
  return Object.freeze(store.getTask(run.taskId)?.projectBindings.map(({ projectId }) => projectId) ?? []);
552
627
  if (view === "reviewer") {
@@ -556,7 +631,9 @@ function writableProjects(store, run, view) {
556
631
  return Object.freeze([]);
557
632
  return Object.freeze(store.getWorkItem(run.taskId, run.workItemId)?.writeProjectIds ?? []);
558
633
  }
559
- function completionActions(view) {
634
+ function completionActions(view, authority) {
635
+ if (authority === "planning")
636
+ return Object.freeze(["finish-turn", "request-input", "request-activation"]);
560
637
  if (view === "leader")
561
638
  return Object.freeze(["finish-turn", "complete-task", "request-input"]);
562
639
  if (view === "reviewer")