@zq-silk/yui 0.15.12 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/ARCHITECTURE.md +3 -2
  2. package/ARCHITECTURE.zh-CN.md +3 -2
  3. package/dist/artifacts/artifactCommitLock.js +16 -55
  4. package/dist/artifacts/taskArtifactRepository.js +3 -3
  5. package/dist/cli/agentConfigurationPicker.js +1 -1
  6. package/dist/cli/commandCatalog.js +57 -41
  7. package/dist/cli/completion.js +18 -18
  8. package/dist/cli/completionWizard.js +1 -1
  9. package/dist/cli/dynamicCompletion.js +1 -1
  10. package/dist/cli/interactionPolicy.js +7 -3
  11. package/dist/cli/invocationAuthority.js +64 -0
  12. package/dist/cli/managedDiagnostics.js +1 -1
  13. package/dist/cli/parseRepeatable.js +35 -0
  14. package/dist/cli/updatePorts.js +26 -5
  15. package/dist/cli.js +1280 -1243
  16. package/dist/commands/agentCommands.js +4 -4
  17. package/dist/commands/capabilityCommands.js +1 -1
  18. package/dist/commands/configCommands.js +6 -57
  19. package/dist/commands/configOverview.js +2 -2
  20. package/dist/commands/durableJobCommands.js +12 -6
  21. package/dist/commands/globalRoleCommands.js +53 -29
  22. package/dist/commands/grantCommands.js +0 -3
  23. package/dist/commands/jobCommands.js +1 -4
  24. package/dist/commands/operatorCommands.js +3 -3
  25. package/dist/commands/projectCommands.js +1 -10
  26. package/dist/commands/resourcesCommands.js +10 -40
  27. package/dist/commands/roleConfiguration.js +2 -6
  28. package/dist/commands/taskActivationCommands.js +4 -8
  29. package/dist/commands/taskAgentCapabilities.js +9 -0
  30. package/dist/commands/taskCommandSupport.js +155 -0
  31. package/dist/commands/taskCommandTypes.js +1 -0
  32. package/dist/commands/taskCommands.js +271 -710
  33. package/dist/commands/taskCompletionGate.js +1 -1
  34. package/dist/commands/taskExecutionCommands.js +1 -1
  35. package/dist/commands/taskFactCommands.js +325 -0
  36. package/dist/commands/taskInputCommands.js +12 -42
  37. package/dist/commands/taskIntegrationCommands.js +17 -57
  38. package/dist/commands/taskNextActionCommand.js +7 -6
  39. package/dist/commands/taskPublicationAdoptCommand.js +3 -3
  40. package/dist/commands/taskPublicationCommands.js +1 -1
  41. package/dist/commands/taskPublicationVerifyCommand.js +1 -1
  42. package/dist/commands/taskRemoteDeliveryCommand.js +2 -94
  43. package/dist/commands/taskUpstreamCommands.js +19 -8
  44. package/dist/commands/workflowCommands.js +6 -1
  45. package/dist/completion/completionInstaller.js +26 -26
  46. package/dist/completion/completionState.js +26 -26
  47. package/dist/completion/fileCompletionManager.js +6 -11
  48. package/dist/config/configCatalog.js +0 -2
  49. package/dist/config/timeZone.js +14 -0
  50. package/dist/config/yuiConfig.js +0 -29
  51. package/dist/context/runContextPack.js +2 -3
  52. package/dist/context/taskCatalog.js +3 -5
  53. package/dist/context/taskContext.js +139 -151
  54. package/dist/context/wakeRunReferences.js +11 -0
  55. package/dist/controller/agentCapabilities.js +58 -0
  56. package/dist/controller/agentRuntimeObserver.js +6 -11
  57. package/dist/controller/clientRuntime.js +22 -14
  58. package/dist/controller/controller.js +9 -22
  59. package/dist/controller/fileSchedulerStoreAdapter.js +117 -212
  60. package/dist/controller/jobClient.js +4 -4
  61. package/dist/controller/jobControl.js +60 -25
  62. package/dist/controller/jobSupervisor.js +4 -4
  63. package/dist/controller/providerRetryDelivery.js +7 -7
  64. package/dist/controller/runtime.js +51 -44
  65. package/dist/controller/runtimeEventProcessor.js +0 -5
  66. package/dist/controller/sessionOwnerReconciliation.js +5 -0
  67. package/dist/controller/taskAgentError.js +35 -0
  68. package/dist/coordination/workMailboxQueue.js +2 -24
  69. package/dist/core/controllerClient.js +2 -2
  70. package/dist/core/fileLockOwner.js +74 -0
  71. package/dist/decision/decision.js +17 -0
  72. package/dist/doctor/doctor.js +18 -9
  73. package/dist/event/taskEvent.js +12 -0
  74. package/dist/execution/workItemExecutionProjection.js +2 -2
  75. package/dist/executor/agentCapabilityConfig.js +43 -0
  76. package/dist/executor/agentConfigurationCatalog.js +49 -11
  77. package/dist/executor/agentExecutor.js +5 -8
  78. package/dist/executor/fileRoleLaunchPlanner.js +11 -53
  79. package/dist/executor/taskAgentCapabilities.js +64 -0
  80. package/dist/integration/deliveryObligation.js +1 -69
  81. package/dist/integration/gitIntegrationService.js +60 -84
  82. package/dist/integration/integrationAttempt.js +3 -14
  83. package/dist/integration/integrationSourceApplication.js +4 -12
  84. package/dist/integration/manifestTags.js +2 -2
  85. package/dist/job/durableJob.js +4 -25
  86. package/dist/job/jobAssignmentScope.js +22 -0
  87. package/dist/job/jobOperation.js +16 -0
  88. package/dist/job/jobRunner.js +2 -1
  89. package/dist/job/stepDirectory.js +15 -0
  90. package/dist/kernel/builtinCapabilities.js +15 -11
  91. package/dist/kernel/kernelPorts.js +1 -17
  92. package/dist/lifecycle/exactRunTerminalization.js +1 -9
  93. package/dist/message/inputControlResolution.js +3 -4
  94. package/dist/message/message.js +17 -20
  95. package/dist/message/messageContinuation.js +1 -1
  96. package/dist/milestone/milestone.js +11 -0
  97. package/dist/observability/orchestrationMetrics.js +24 -1
  98. package/dist/observability/runtimeIdentity.js +1 -17
  99. package/dist/output/agentConfigurationPresentation.js +2 -0
  100. package/dist/output/timePresentation.js +1 -14
  101. package/dist/plugins/pluginService.js +12 -4
  102. package/dist/release/releaseWorkflowPorts.js +45 -96
  103. package/dist/release/runtimeRelease.js +9 -15
  104. package/dist/repository/projectMaintenanceLock.js +23 -64
  105. package/dist/repository/taskBaseFreshness.js +1 -1
  106. package/dist/repository/taskWorkspaceCoordinator.js +13 -22
  107. package/dist/repository/taskWorkspacePreparer.js +29 -25
  108. package/dist/repository/workspaceCleanupInspection.js +5 -5
  109. package/dist/resources/autoResourceGc.js +4 -77
  110. package/dist/resources/liveReferences.js +7 -54
  111. package/dist/resources/resourceDiscovery.js +5 -118
  112. package/dist/resources/resourceGc.js +233 -181
  113. package/dist/resources/resourceRegistrar.js +5 -4
  114. package/dist/resources/resourceRegistry.js +3 -37
  115. package/dist/resources/resourceRegistryStore.js +13 -36
  116. package/dist/resources/sqliteResourceRegistry.js +43 -26
  117. package/dist/review/deltaRecheck.js +1 -1
  118. package/dist/review/reviewAcceptance.js +1 -1
  119. package/dist/review/reviewDecision.js +1 -1
  120. package/dist/review/reviewRound.js +8 -7
  121. package/dist/review/taskFinalReviewContractResolution.js +1 -1
  122. package/dist/runtime/acpProtocol.js +4 -51
  123. package/dist/runtime/acpSession.js +10 -75
  124. package/dist/runtime/acpSessionConfiguration.js +1 -8
  125. package/dist/runtime/agentEndpoint.js +3 -2
  126. package/dist/runtime/agentFailureContext.js +43 -0
  127. package/dist/runtime/agentHost.js +15 -15
  128. package/dist/runtime/codexInteractiveHost.js +2 -2
  129. package/dist/runtime/index.js +0 -1
  130. package/dist/runtime/managedCaller.js +21 -1
  131. package/dist/runtime/providerErrors.js +38 -0
  132. package/dist/runtime/runtimeObservation.js +0 -5
  133. package/dist/runtime/runtimeSessionCandidate.js +2 -3
  134. package/dist/runtime/sessionOwnerIdentity.js +1 -1
  135. package/dist/runtime/structuredProviderHost.js +4 -41
  136. package/dist/runtime/tmuxAdapters.js +6 -8
  137. package/dist/scheduler/activeRoleRunDelivery.js +7 -7
  138. package/dist/scheduler/leaderWakeupProcessor.js +19 -6
  139. package/dist/scheduler/operatorEvent.js +12 -20
  140. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  141. package/dist/scheduler/ports.js +5 -8
  142. package/dist/scheduler/roleRunLiveness.js +4 -4
  143. package/dist/scheduler/roleRunStall.js +16 -23
  144. package/dist/scheduler/taskExecutionProjection.js +25 -33
  145. package/dist/scheduler/taskObservabilityProjection.js +0 -1
  146. package/dist/scheduler/taskWake.js +5 -10
  147. package/dist/scheduler/wakeReason.js +2 -0
  148. package/dist/scheduler/wakeupQueue.js +2 -4
  149. package/dist/setup/setupCommand.js +1 -1
  150. package/dist/storage/contextRecords.js +106 -0
  151. package/dist/storage/currentTaskStore.js +1 -1
  152. package/dist/storage/homeLayout.js +13 -17
  153. package/dist/storage/migrations/agentFailureContext.js +22 -0
  154. package/dist/storage/migrations/currentInputContract.js +86 -0
  155. package/dist/storage/migrations/currentRuntimeContract.js +228 -0
  156. package/dist/storage/migrations/historicalVerificationPlan.js +35 -0
  157. package/dist/storage/migrations/integrationContinuation.js +5 -4
  158. package/dist/storage/migrations/narrowAgentFailureContext.js +65 -0
  159. package/dist/storage/migrations/notificationOnlyWakes.js +74 -0
  160. package/dist/storage/migrations/verificationPlanV1.js +162 -0
  161. package/dist/storage/migrations/verificationPolicy.js +74 -0
  162. package/dist/storage/migrations/workItemHistory.js +46 -0
  163. package/dist/storage/persistenceWorker.js +12 -4
  164. package/dist/storage/recordValidation.js +87 -0
  165. package/dist/storage/sqliteSchema.js +142 -1
  166. package/dist/storage/sqliteStore.js +156 -162
  167. package/dist/storage/storageSchema.js +2 -14
  168. package/dist/storage/storageVersions.js +1 -1
  169. package/dist/storage/storeRpc.js +15 -7
  170. package/dist/storage/taskStore.js +3 -7
  171. package/dist/storage/upgrade/upgradeOrchestrator.js +25 -37
  172. package/dist/task/completionReadiness.js +5 -24
  173. package/dist/task/draftPlan.js +0 -53
  174. package/dist/task/nextAction.js +7 -13
  175. package/dist/task/remoteDeliveryService.js +89 -0
  176. package/dist/task/taskActivation.js +2 -25
  177. package/dist/task/taskActivationService.js +0 -2
  178. package/dist/task/taskRecordReference.js +0 -1
  179. package/dist/task/taskSubmission.js +3 -14
  180. package/dist/telemetry/sqliteTelemetryBatch.js +29 -0
  181. package/dist/telemetry/sqliteTelemetryStore.js +49 -49
  182. package/dist/telemetry/telemetryWiring.js +4 -3
  183. package/dist/tmux/tmuxManager.js +29 -20
  184. package/dist/verification/gateArtifact.js +15 -24
  185. package/dist/verification/gateArtifactStore.js +14 -7
  186. package/dist/verification/verificationGateService.js +29 -88
  187. package/dist/verification/verificationPlan.js +27 -72
  188. package/dist/web/assets/client/app.js +1 -1
  189. package/dist/web/assets/client/taskSurface.js +4 -4
  190. package/dist/web/webServer.js +4 -6
  191. package/dist/web/webSnapshot.js +3 -83
  192. package/dist/web/webTaskSurface.js +17 -46
  193. package/dist/workItem/workItem.js +1 -12
  194. package/docs/architecture/capabilities-and-resources.md +14 -2
  195. package/docs/architecture/capabilities-and-resources.zh-CN.md +11 -1
  196. package/docs/managed-turn-and-session-runtime.md +83 -10
  197. package/docs/managed-turn-and-session-runtime.zh-CN.md +65 -11
  198. package/docs/plugin-sdk.md +4 -2
  199. package/docs/provider-runtime.md +3 -1
  200. package/docs/provider-runtime.zh-CN.md +4 -2
  201. package/docs/release-workflow.md +190 -7
  202. package/docs/release-workflow.zh-CN.md +139 -5
  203. package/docs/roles-and-configuration.md +29 -0
  204. package/docs/roles-and-configuration.zh-CN.md +21 -0
  205. package/docs/sqlite-control-plane-design.md +16 -3
  206. package/docs/sqlite-control-plane-design.zh-CN.md +13 -2
  207. package/docs/task-dag-semantics.md +3 -3
  208. package/docs/task-dag-semantics.zh-CN.md +2 -2
  209. package/docs/task-delivery.md +91 -5
  210. package/docs/task-delivery.zh-CN.md +72 -4
  211. package/docs/task-discovery.md +10 -11
  212. package/docs/task-discovery.zh-CN.md +8 -9
  213. package/docs/testing/verification-levels.md +145 -9
  214. package/docs/testing/verification-levels.zh-CN.md +103 -8
  215. package/package.json +1 -1
  216. package/skills/yui-leader/SKILL.md +5 -0
  217. package/skills/yui-leader/references/integration.md +9 -5
  218. package/skills/yui-leader/references/planning.md +9 -3
  219. package/skills/yui-operator/SKILL.md +15 -10
  220. package/skills/yui-runtime/SKILL.md +6 -6
  221. package/skills/yui-runtime/references/recovery.md +47 -0
  222. package/dist/agent/agentRegistry.js +0 -10
  223. package/dist/agentRun/runIdentity.js +0 -22
  224. package/dist/commands/deliveryGuardPreflight.js +0 -30
  225. package/dist/commands/taskIntegrationQueueCommands.js +0 -226
  226. package/dist/commands/taskOverviewCommand.js +0 -377
  227. package/dist/completion/completionWizard.js +0 -125
  228. package/dist/context/dispatchContext.js +0 -110
  229. package/dist/context/wakeNotification.js +0 -144
  230. package/dist/integration/integrationCheckEvidenceReuse.js +0 -53
  231. package/dist/integration/integrationQueueEntry.js +0 -191
  232. package/dist/integration/integrationQueueService.js +0 -810
  233. package/dist/release/fakeReleasePorts.js +0 -55
  234. package/dist/runtime/sessionOwnerRegistry.js +0 -137
  235. package/dist/task/deliveryGuard.js +0 -226
  236. /package/dist/{commands/taskActor.js → task/taskAuthority.js} +0 -0
@@ -16,23 +16,11 @@ export class StorageSchemaError extends Error {
16
16
  /**
17
17
  * Inspect the one authoritative SQLite migration head without changing it.
18
18
  *
19
- * `schema.json` and `state.json` are recognized only to prevent setup from
20
- * overwriting an old Home whose SQLite authority is missing. They are not
21
- * version authorities for current Homes.
19
+ * Extra files never override the SQLite authority. A missing database in a
20
+ * non-empty Home is unverified, not permission to initialize over its evidence.
22
21
  */
23
22
  export function inspectStorageSchema(rootDir) {
24
23
  const databasePath = join(rootDir, CURRENT_DATABASE_FILENAME);
25
- const hasPreBaselineEvidence = existsSync(join(rootDir, "schema.json")) || existsSync(join(rootDir, "state.json"));
26
- if (hasPreBaselineEvidence) {
27
- return {
28
- status: "unsupported",
29
- direction: "older",
30
- currentVersion: 0,
31
- latestVersion: CURRENT_STORAGE_VERSION,
32
- minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
33
- databasePath
34
- };
35
- }
36
24
  if (!existsSync(databasePath)) {
37
25
  if (existsSync(rootDir)) {
38
26
  try {
@@ -13,4 +13,4 @@
13
13
  * intermediate Yui releases.
14
14
  */
15
15
  export const MIN_SUPPORTED_STORAGE_VERSION = 1;
16
- export const CURRENT_STORAGE_VERSION = 27;
16
+ export const CURRENT_STORAGE_VERSION = 37;
@@ -8,7 +8,8 @@
8
8
  *
9
9
  * - {@link AsyncTaskStore} ........ the async counterpart to `TaskStore`
10
10
  * (design §6): every method returns a promise; the worker owns the
11
- * `SqliteTaskStore` connection, the main thread never touches the db.
11
+ * worker-side connection. The Controller's separate synchronous scheduler
12
+ * connection is not routed through this interface.
12
13
  * - {@link AsyncTaskStoreClient} .. the client: serializes requests, applies
13
14
  * the storage idempotency/dialect rules on top of the shared bounded RPC
14
15
  * (outbox §5.4, `AbortSignal` cancellation §3.1, restart + replay §3.1).
@@ -16,8 +17,8 @@
16
17
  * `transactionAsync` ships an ordered batch that the worker runs inside one
17
18
  * `BEGIN IMMEDIATE … COMMIT` (§3.2).
18
19
  *
19
- * SQLite is the only product Store. `YUI_STORE_WORKER` controls whether its
20
- * connection lives in a Worker Thread; it does not select another authority.
20
+ * SQLite is the only product Store. `YUI_STORE_WORKER` selects the observer
21
+ * execution boundary; it does not select another authority.
21
22
  */
22
23
  import { BoundedRpcClient, nextRequestId } from "../core/boundedRpc.js";
23
24
  import { StorageCancelledError, StorageConflictError, StorageRecordError } from "./taskStore.js";
@@ -51,6 +52,12 @@ const READ_ONLY_STORE_METHODS = new Set([
51
52
  "getTask",
52
53
  "readNextActionFacts",
53
54
  "readCompletionReadinessFacts",
55
+ "queryContextRecords",
56
+ "latestEventSequence",
57
+ "listEventsByType",
58
+ "listTaskRunWorkspaceBases",
59
+ "contextInputReferences",
60
+ "listActiveRuns",
54
61
  "listActiveTaskIds",
55
62
  "listPlanningDraftTaskIds",
56
63
  "listPendingActivationRequestTaskIds",
@@ -168,12 +175,8 @@ function storageProtocol(home, options) {
168
175
  * RPCs) plus {@link transactionAsync}, {@link invokeObserver}, and {@link close}.
169
176
  */
170
177
  export class AsyncTaskStoreClient {
171
- #home;
172
- #options;
173
178
  #rpc;
174
179
  constructor(home, options = {}) {
175
- this.#home = home;
176
- this.#options = options;
177
180
  this.#rpc = new BoundedRpcClient(storageProtocol(home, options), {
178
181
  maxInFlight: options.maxInFlight,
179
182
  maxQueue: options.maxQueue,
@@ -218,6 +221,11 @@ export class AsyncTaskStoreClient {
218
221
  close() {
219
222
  return this.#rpc.close();
220
223
  }
224
+ /** Best-effort diagnostic batch on this worker, without a Task outbox entry. */
225
+ async flushTelemetry(entries, runCap) {
226
+ const requestId = nextRequestId();
227
+ await this.#rpc.send(requestId, { kind: "telemetry", requestId, entries, runCap });
228
+ }
221
229
  /** Currently in-flight requests (metrics/tests). */
222
230
  get inFlight() {
223
231
  return this.#rpc.inFlight;
@@ -2,12 +2,12 @@ import { lstatSync, mkdirSync, realpathSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { basename, dirname, join, resolve } from "node:path";
4
4
  import { isDeepStrictEqual } from "node:util";
5
+ import { resolveTimeZone } from "../config/timeZone.js";
6
+ import { reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveResourcesGcAutoQuarantine, resolveResourcesGcMode, resolveResourcesQuarantineTtlHours, resolveRuntimeHealth, resolveTelemetryEnabled, resolveTelemetryRunCap, resolveTelemetryTerminalKeep, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
5
7
  import { validateCapabilityGrant } from "../grant/capabilityGrant.js";
6
8
  import { validateReleaseWorkflow } from "../release/releaseWorkflow.js";
7
- import { validatePublicationReference } from "../task/publicationReference.js";
8
- import { reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveLeaderNextActionMode, resolveLeaderSemanticBudgetRuns, resolveResourcesGcAutoQuarantine, resolveResourcesGcMode, resolveResourcesQuarantineTtlHours, resolveRuntimeHealth, resolveTelemetryEnabled, resolveTelemetryRunCap, resolveTelemetryTerminalKeep, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
9
- import { resolveTimeZone } from "../output/timePresentation.js";
10
9
  import { validateReviewConfig } from "../review/reviewConfig.js";
10
+ import { validatePublicationReference } from "../task/publicationReference.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. */
@@ -151,12 +151,10 @@ export function validateYuiConfig(config) {
151
151
  "resourcesGcMode",
152
152
  "resourcesGcAutoQuarantine",
153
153
  "review",
154
- "leaderNextActionMode",
155
154
  "runtimeHealth",
156
155
  "controllerTaskConcurrency",
157
156
  "agentLaunchInactivityTimeoutSeconds",
158
157
  "deliveryTimeoutSeconds",
159
- "leaderSemanticBudgetRuns",
160
158
  "resourcesQuarantineTtlHours",
161
159
  "tmuxBin",
162
160
  "tmuxHistoryLimit",
@@ -176,7 +174,6 @@ export function validateYuiConfig(config) {
176
174
  resolveTimeZone(config.timeZone);
177
175
  if (config.review !== undefined)
178
176
  validateReviewConfig(config.review);
179
- resolveLeaderNextActionMode(config.leaderNextActionMode);
180
177
  resolveResourcesGcMode(config.resourcesGcMode);
181
178
  resolveResourcesGcAutoQuarantine(config.resourcesGcAutoQuarantine);
182
179
  resolveResourcesQuarantineTtlHours(config.resourcesQuarantineTtlHours);
@@ -184,7 +181,6 @@ export function validateYuiConfig(config) {
184
181
  resolveControllerTaskConcurrency(config.controllerTaskConcurrency);
185
182
  resolveAgentLaunchInactivityTimeoutSeconds(config.agentLaunchInactivityTimeoutSeconds);
186
183
  resolveDeliveryTimeoutSeconds(config.deliveryTimeoutSeconds);
187
- resolveLeaderSemanticBudgetRuns(config.leaderSemanticBudgetRuns);
188
184
  resolveTmuxBin(config.tmuxBin);
189
185
  resolveTmuxHistoryLimit(config.tmuxHistoryLimit);
190
186
  resolveTelemetryEnabled(config.telemetryEnabled);
@@ -4,16 +4,14 @@ import Database from "better-sqlite3";
4
4
  import { inspectAgentHostCompatibility, describeAgentHostUpgradeBlockers } from "../../runtime/agentHostCompatibility.js";
5
5
  import { RUNTIME_OBSERVATION_TASK_EVENT, createRuntimeObservation } from "../../runtime/runtimeObservation.js";
6
6
  import { RUNTIME_PROCESS_EXIT_TASK_EVENT, validateRuntimeProcessExitObservation } from "../../runtime/processExitObservation.js";
7
- import { validateAgentProfile } from "../../profile/agentProfile.js";
8
- import { validateRoleSessionSet } from "../../executor/agentExecutor.js";
9
- import { validateReviewRound } from "../../review/reviewRound.js";
10
- import { validateRun } from "../../agentRun/agentRun.js";
11
- import { validateDurableJob } from "../../job/durableJob.js";
12
- import { validateWorkItem } from "../../workItem/workItem.js";
13
7
  import { SqliteTaskStore } from "../sqliteStore.js";
14
8
  import { storageBackupRoot } from "../homeLayout.js";
15
9
  import { preflightUnifyHomeLayout } from "../migrations/unifyHomeLayout.js";
16
10
  import { preflightCollapseWorktreeLayout } from "../migrations/collapseWorktreeLayout.js";
11
+ import { preflightNotificationOnlyWakes } from "../migrations/notificationOnlyWakes.js";
12
+ import { preflightVerificationPolicy } from "../migrations/verificationPolicy.js";
13
+ import { preflightCurrentInputContract } from "../migrations/currentInputContract.js";
14
+ import { preflightCurrentRuntimeContract } from "../migrations/currentRuntimeContract.js";
17
15
  import { migrateSqliteSchema, storageMigrationPlan } from "../sqliteSchema.js";
18
16
  import { CURRENT_DATABASE_FILENAME, inspectStorageSchema } from "../storageSchema.js";
19
17
  import { CURRENT_STORAGE_VERSION, MIN_SUPPORTED_STORAGE_VERSION } from "../storageVersions.js";
@@ -153,7 +151,6 @@ export async function runStorageUpgrade(options) {
153
151
  database.close();
154
152
  }
155
153
  validateCurrentStore(options.home);
156
- rmSync(join(options.home, "schema.json"), { force: true });
157
154
  }
158
155
  catch (error) {
159
156
  const restoration = migrationCommitted
@@ -206,29 +203,8 @@ export async function runStorageUpgrade(options) {
206
203
  function validateCurrentStore(home) {
207
204
  const store = new SqliteTaskStore(home);
208
205
  try {
209
- store.getConfig();
210
- for (const profile of store.listAgentProfiles())
211
- validateAgentProfile(profile);
212
- for (const sessions of store.listGlobalRoleSessionSets()) {
213
- validateRoleSessionSet(sessions);
214
- }
215
- for (const owner of store.listSessionOwners()) {
216
- if (owner.schemaVersion !== 2 || Object.hasOwn(owner, "launchId")) {
217
- throw new Error("Session owner runtime identity is invalid.");
218
- }
219
- }
206
+ store.validateCurrentRecords();
220
207
  for (const taskId of store.listTasks().map(({ id }) => id)) {
221
- for (const job of store.listDurableJobs(taskId))
222
- validateDurableJob(job);
223
- for (const item of store.listWorkItems(taskId))
224
- validateWorkItem(item);
225
- for (const round of store.listReviewRounds(taskId))
226
- validateReviewRound(round);
227
- for (const run of store.listRuns(taskId))
228
- validateRun(run);
229
- for (const sessions of store.listRoleSessionSets(taskId)) {
230
- validateRoleSessionSet(sessions);
231
- }
232
208
  for (const event of store.listEvents(taskId)) {
233
209
  if (event.type === RUNTIME_OBSERVATION_TASK_EVENT) {
234
210
  createRuntimeObservation(JSON.parse(event.payload.observation ?? ""));
@@ -345,16 +321,17 @@ function blocked(classification, stage, message, action) {
345
321
  };
346
322
  }
347
323
  /**
348
- * Run each path-relocating data migration's READ-ONLY preflight against the
324
+ * Run each data migration's registered READ-ONLY preflight against the
349
325
  * current (pre-upgrade) database and, when any finds a blocker, return a
350
326
  * `blocked` result the caller surfaces before touching the Controller or the
351
- * Home. Returns `null` when the plan carries no path-relocating data migration,
327
+ * Home. Returns `null` when the plan carries no registered readiness check,
352
328
  * or when every preflight is clear.
353
329
  *
354
- * Both the 18->19 unify and the 19->20 collapse migrations physically relocate
330
+ * Both the 23->24 unify and the 24->25 collapse migrations physically relocate
355
331
  * managed worktrees and share the same blocker shape (in-flight Job, conflicting
356
332
  * relocation target). When a Home is upgraded across both in one run, their
357
- * blockers are aggregated so the operator sees every readiness problem at once.
333
+ * blockers are aggregated so the operator sees their readiness problems together.
334
+ * Notification retirement separately rejects unsettled execution references.
358
335
  *
359
336
  * The database is opened read-only so the checks cannot mutate the authoritative
360
337
  * store, and the handle is always closed. An unexpected failure to evaluate a
@@ -364,8 +341,11 @@ function blocked(classification, stage, message, action) {
364
341
  function preflightMigrationBlockers(home, plan, classification) {
365
342
  const relocatesUnify = plan.some((step) => step.name === "unify-home-layout");
366
343
  const relocatesCollapse = plan.some((step) => step.name === "collapse-worktree-layout");
367
- // Only meaningful when the plan actually includes a path-relocating migration.
368
- if (!relocatesUnify && !relocatesCollapse)
344
+ const retiresRunWakes = plan.some((step) => step.name === "notification-only-wakes");
345
+ const changesVerification = plan.some(step => step.name === "advisory-and-verification-policy");
346
+ const changesInput = plan.some(step => step.name === "current-input-contract");
347
+ const retiresRuntime = plan.some(step => step.name === "current-verification-and-owner-contract");
348
+ if (!relocatesUnify && !relocatesCollapse && !retiresRunWakes && !changesVerification && !changesInput && !retiresRuntime)
369
349
  return null;
370
350
  let blockers;
371
351
  try {
@@ -379,6 +359,14 @@ function preflightMigrationBlockers(home, plan, classification) {
379
359
  blockers.push(...preflightUnifyHomeLayout(database).blockers);
380
360
  if (relocatesCollapse)
381
361
  blockers.push(...preflightCollapseWorktreeLayout(database).blockers);
362
+ if (retiresRunWakes)
363
+ preflightNotificationOnlyWakes(database);
364
+ if (changesVerification)
365
+ preflightVerificationPolicy(database);
366
+ if (changesInput)
367
+ preflightCurrentInputContract(database);
368
+ if (retiresRuntime)
369
+ preflightCurrentRuntimeContract(database);
382
370
  }
383
371
  finally {
384
372
  database.close();
@@ -386,8 +374,8 @@ function preflightMigrationBlockers(home, plan, classification) {
386
374
  }
387
375
  catch (error) {
388
376
  return {
389
- ...blocked(classification, "in-flight", `The storage migration readiness check could not be completed: ${messageOf(error)}`, "Resolve the reported problem, confirm no Job is queued or running against a managed "
390
- + "workspace, then rerun the upgrade.")
377
+ ...blocked(classification, "in-flight", `The storage migration readiness check could not be completed: ${messageOf(error)}`, "Resolve the named execution or resource boundary, preserving original input and results. "
378
+ + "Confirm the relevant Runs and Jobs are settled, then rerun the upgrade.")
391
379
  };
392
380
  }
393
381
  if (blockers.length === 0)
@@ -17,18 +17,13 @@ export function pendingCompletionMessages(store, taskId) {
17
17
  const ids = new Set(refs.filter(ref => ref.type === "message" && ref.taskId === taskId).map(ref => ref.id));
18
18
  return operationalTaskRecords(store.listMessages(taskId), store.listEvents(taskId), "message")
19
19
  .filter(message => ids.has(message.id)
20
- && (message.kind === "user" || message.kind === "operator") && message.wakePolicy !== "none");
20
+ && (message.kind === "user" || message.kind === "operator"));
21
21
  }
22
22
  const ACTIVE_JOB_STATUSES = new Set([
23
23
  "queued",
24
24
  "running",
25
25
  "unknown-needs-attention"
26
26
  ]);
27
- const UNRESOLVED_INTEGRATION_STATUSES = new Set([
28
- "running",
29
- "blocked",
30
- "validating"
31
- ]);
32
27
  const TERMINAL_REVIEW_STATUSES = new Set(["completed", "failed"]);
33
28
  const TERMINAL_LANE_STATUSES = new Set(["completed", "failed", "skipped"]);
34
29
  export function projectCompletionReadiness(facts) {
@@ -45,7 +40,7 @@ export function projectCompletionReadiness(facts) {
45
40
  }
46
41
  // A pending/running Task-final Review must be resumed or blocked first.
47
42
  for (const round of facts.reviewRounds) {
48
- if ((round.scope ?? "work-item") !== "task")
43
+ if (round.scope !== "task")
49
44
  continue;
50
45
  if (round.status !== "pending" && round.status !== "running")
51
46
  continue;
@@ -103,11 +98,9 @@ export function projectCompletionReadiness(facts) {
103
98
  fix: `yui task integration start ${task.id} --work-item ${delivery.workItemId} --project ${delivery.projectId} --strategy <ff|cherry-pick|merge|manual>`
104
99
  });
105
100
  }
106
- // Current delivery Attempts and any Attempt that may still be writing must
107
- // settle. Historical blocked Attempts remain audit evidence only.
101
+ // Unsettled attempts must be explicitly resolved; terminal history remains
102
+ // evidence and is not a second delivery workflow.
108
103
  for (const integration of facts.integrations) {
109
- if (!UNRESOLVED_INTEGRATION_STATUSES.has(integration.status))
110
- continue;
111
104
  if (!integrationAttemptRequiresSettlement(integration))
112
105
  continue;
113
106
  blockers.push({
@@ -117,18 +110,6 @@ export function projectCompletionReadiness(facts) {
117
110
  fix: `yui task integration continue ${task.id}/${integration.id}`
118
111
  });
119
112
  }
120
- // Legacy queue entries may still launch an Integration and therefore must
121
- // settle even though ChangeSets are no longer delivery authority.
122
- for (const entry of facts.integrationQueueEntries) {
123
- if (entry.status === "committed" || entry.status === "superseded")
124
- continue;
125
- blockers.push({
126
- code: "unsettled-integration-queue-entry",
127
- ref: ref("integration-queue-entry", entry.id),
128
- reason: `Integration queue entry ${entry.id} is ${entry.status}.`,
129
- fix: `settle integration queue entry ${entry.id} (continue or supersede)`
130
- });
131
- }
132
113
  // Terminal child workspaces are cleanup advisories: Task completion is the
133
114
  // semantic delivery boundary, while archive remains the fail-closed resource
134
115
  // reclamation boundary. Missing/non-terminal ownership stays conservative.
@@ -198,7 +179,7 @@ function workspaceCompletionDisposition(facts, taskId, workspace) {
198
179
  }
199
180
  case "integration-attempt": {
200
181
  const integration = facts.integrations.find((entry) => entry.id === owner.integrationAttemptId);
201
- if (integration !== undefined && UNRESOLVED_INTEGRATION_STATUSES.has(integration.status)) {
182
+ if (integration !== undefined && integrationAttemptRequiresSettlement(integration)) {
202
183
  return null;
203
184
  }
204
185
  const value = {
@@ -1,25 +1,4 @@
1
- import { RUNTIME_OBSERVATION_TASK_EVENT } from "../runtime/runtimeObservation.js";
2
1
  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
- ]);
23
2
  export function assertDraftTaskExecutionFree(store, task) {
24
3
  if (task.status !== "draft") {
25
4
  throw new Error(`Task is not a Draft: ${task.id}/${task.status}.`);
@@ -168,35 +147,3 @@ function firstDraftExecutionFact(store, task) {
168
147
  // of delivery authority. The domain records above own delivery facts.
169
148
  return undefined;
170
149
  }
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;
202
- }
@@ -1,11 +1,11 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { actionableExecutionLaneRecoveries } from "../execution/executionHealth.js";
2
3
  import { governingWorkItemDeliveries, workItemDeliverySettled } from "../integration/deliveryObligation.js";
3
4
  import { isCompletedTaskReviewEvidenceFromRuns } from "../review/reviewAcceptance.js";
4
- import { actionableExecutionLaneRecoveries } from "../execution/executionHealth.js";
5
5
  import { sameTaskFinalReviewContract } from "../review/taskFinalReviewContract.js";
6
6
  import { resolveRecordedTaskFinalReviewContract } from "../review/taskFinalReviewContractResolution.js";
7
- import { draftWorkItemDependencyIssue } from "./draftPlan.js";
8
7
  import { currentWorkItemCandidate, currentWorkItemExecutionGroup, governingWorkItemCandidate } from "../workItem/workItem.js";
8
+ import { draftWorkItemDependencyIssue } from "./draftPlan.js";
9
9
  const OPEN_WORK_ITEM_STATUSES = new Set(["open"]);
10
10
  export function projectNextAction(facts) {
11
11
  const { task } = facts;
@@ -150,7 +150,7 @@ export function projectNextAction(facts) {
150
150
  }
151
151
  return buildAction(facts, {
152
152
  kind: "integrate-work-item",
153
- reason: `Integration ${checkingIntegration.id} awaits check-result consumption (${job?.status ?? "read current Job"}); an empty integration queue does not finalize this direct attempt.`,
153
+ reason: `Integration ${checkingIntegration.id} awaits check-result consumption (${job?.status ?? "read current Job"}); its exact Job must be consumed to finalize the attempt.`,
154
154
  refs,
155
155
  preconditions: [{ fact: "The Integration retains its exact check Job", satisfied: true, ref: refs[0] }],
156
156
  recommendedCommand: `yui task integration continue ${task.id}/${checkingIntegration.id}`
@@ -378,7 +378,7 @@ export function projectNextAction(facts) {
378
378
  }
379
379
  if (deliveryWorkItems.length === 0
380
380
  && !taskFinalReviewRequired(facts)
381
- && !facts.reviewRounds.some((round) => ((round.scope ?? "work-item") === "task"
381
+ && !facts.reviewRounds.some((round) => (round.scope === "task"
382
382
  && (round.status === "pending" || round.status === "running")))) {
383
383
  const reviewAlternative = facts.reviewConfig === null
384
384
  ? []
@@ -675,7 +675,6 @@ export function durableStateFingerprint(facts) {
675
675
  ...facts.workItems.map((item) => `work:${item.id}:${item.status}:${item.revision}:${item.updatedAt}`),
676
676
  ...facts.changeSets.map((changeSet) => `change-set:${changeSet.id}:${changeSet.headCommit}`),
677
677
  ...facts.integrations.map((attempt) => `integration:${attempt.id}:${attempt.status}:${attempt.updatedAt}`),
678
- ...facts.integrationQueueEntries.map((entry) => `integration-queue:${entry.id}:${entry.status}:${entry.updatedAt}`),
679
678
  ...facts.reviewRounds.map((round) => `review:${round.id}:${round.status}:${round.endedAt ?? ""}`)
680
679
  ];
681
680
  return createHash("sha256").update(parts.join("\n")).digest("hex");
@@ -819,22 +818,17 @@ function taskFinalReviewRole(facts) {
819
818
  function ref(kind, id) {
820
819
  return { kind, id };
821
820
  }
822
- function latestFailedReviewFor(rounds, workItemId) {
823
- return [...rounds]
824
- .reverse()
825
- .find((round) => round.workItemId === workItemId && round.status === "failed");
826
- }
827
821
  function latestTaskFinalReview(rounds, contract) {
828
822
  return [...rounds]
829
823
  .reverse()
830
- .find((round) => ((round.scope ?? "work-item") === "task"
824
+ .find((round) => (round.scope === "task"
831
825
  && (contract === undefined || sameTaskFinalReviewContract(round.taskFinalReviewContract, contract))));
832
826
  }
833
827
  function hasValidFinalReview(facts) {
834
828
  const contract = taskFinalReviewContract(facts);
835
829
  const final = [...facts.reviewRounds]
836
830
  .reverse()
837
- .find((round) => ((round.scope ?? "work-item") === "task"
831
+ .find((round) => (round.scope === "task"
838
832
  && (contract === undefined || sameTaskFinalReviewContract(round.taskFinalReviewContract, contract))));
839
833
  if (final === undefined || !isCompletedTaskReviewEvidenceFromRuns(final, facts.reviewOutcomeEvidence?.runs ?? []))
840
834
  return false;
@@ -853,7 +847,7 @@ function detectProtocolInconsistency(facts) {
853
847
  : [ref("candidate", `${item.id}/${candidate.id}`)];
854
848
  });
855
849
  const reviewRefs = facts.reviewRounds
856
- .filter((round) => ((round.scope ?? "work-item") === "task"
850
+ .filter((round) => (round.scope === "task"
857
851
  && round.taskFinalReviewContract !== undefined))
858
852
  .map((round) => ref("review-round", round.id));
859
853
  return {
@@ -0,0 +1,89 @@
1
+ import { isDeepStrictEqual } from "node:util";
2
+ import { usageError } from "../errors/cliError.js";
3
+ import { projectTaskRemoteDelivery } from "../task/remoteDelivery.js";
4
+ import { PUBLICATION_ADOPTED_EVENT } from "./publicationAdoption.js";
5
+ export function projectTaskRemoteDeliveryFromStore(store, task, currentCandidate = null) {
6
+ return createTaskRemoteDeliveryProof(store, task, currentCandidate).delivery;
7
+ }
8
+ export function createTaskRemoteDeliveryProof(store, task, currentCandidate = null) {
9
+ const publications = store.listPublicationReferences(task.id);
10
+ const delivery = projectTaskRemoteDelivery({
11
+ task,
12
+ events: store.listEventsByType(task.id, [
13
+ "task.completed", "task.archived", PUBLICATION_ADOPTED_EVENT
14
+ ]),
15
+ publications,
16
+ managedWorkspaces: store.listManagedWorkspaces(task.id),
17
+ runs: task.projectBindings.length === 0 ? [] : store.listTaskRunWorkspaceBases(task.id),
18
+ integrations: store.listIntegrationAttempts(task.id),
19
+ currentCandidate
20
+ });
21
+ return {
22
+ schemaVersion: 1,
23
+ task: taskRemoteDeliveryProofTask(task),
24
+ publications,
25
+ delivery
26
+ };
27
+ }
28
+ export function assertTaskRemoteDeliveryProof(store, task, proof) {
29
+ if (proof === undefined || proof.schemaVersion !== 1) {
30
+ throw usageError(`Task remote-delivery preflight proof is required: ${task.id}.`);
31
+ }
32
+ if (!isDeepStrictEqual(proof.task, taskRemoteDeliveryProofTask(task))) {
33
+ throw usageError(`Task changed after remote-delivery preflight: ${task.id}.`);
34
+ }
35
+ if (!isDeepStrictEqual(proof.publications, store.listPublicationReferences(task.id))) {
36
+ throw usageError(`Task Publication evidence changed after remote-delivery preflight: ${task.id}.`);
37
+ }
38
+ // Recheck semantic adoption/Integration facts as well as Publication versions.
39
+ // For provisional cancelled Tasks retain the frozen candidate used at preflight.
40
+ const current = projectTaskRemoteDeliveryFromStore(store, task, {
41
+ projects: proof.delivery.projects.flatMap(p => p.expectedLocalCommit === null
42
+ ? [] : [{ projectId: p.projectId, commit: p.expectedLocalCommit }])
43
+ });
44
+ if (!isDeepStrictEqual(current, proof.delivery)) {
45
+ throw usageError(`Task delivery evidence changed after remote-delivery preflight: ${task.id}.`);
46
+ }
47
+ assertTaskRemoteDeliveryIntegrated(proof.delivery);
48
+ return proof.delivery;
49
+ }
50
+ export function assertTaskRemoteDeliveryIntegrated(delivery) {
51
+ if (!delivery.allMerged) {
52
+ const headUnavailable = delivery.projects.filter((project) => (project.codeDelivery !== "none"
53
+ && project.coverage === "head-unavailable"));
54
+ if (headUnavailable.length > 0 && delivery.source === "task-completed") {
55
+ throw usageError(`Task ${delivery.taskId} has no frozen completion heads for: ${headUnavailable.map(({ projectId }) => projectId).join(", ")}. Historical acceptance cannot be inferred from a merge or archive.`);
56
+ }
57
+ const uncovered = delivery.projects
58
+ .filter((project) => project.codeDelivery !== "none" && !project.merged)
59
+ .map((project) => (`${project.projectId}/${project.coverage}`
60
+ + (project.publication === null ? "" : `/${project.publication.id}`)))
61
+ .join(", ");
62
+ throw usageError(`Task ${delivery.taskId} is not fully merged into remote delivery: ${uncovered || "expected Project heads are unavailable"}. Inspect each Project reason with task remote-delivery. Record confirmed Publication facts; `
63
+ + "for a changed post-completion candidate, review publication diff and explicitly adopt its acceptance.");
64
+ }
65
+ if (delivery.allVerified)
66
+ return;
67
+ const unverified = delivery.projects
68
+ .filter((project) => (project.codeDelivery !== "none"
69
+ && project.merged
70
+ && !project.verified))
71
+ .map((project) => (`${project.projectId}/${project.coverage}`
72
+ + (project.publication === null ? "" : `/${project.publication.id}`)))
73
+ .join(", ");
74
+ throw usageError(`Task ${delivery.taskId} has merged Publication evidence that is not verified: `
75
+ + `${unverified || "verification evidence is unavailable"}. Run task publication verify `
76
+ + "for each Publication only when the provider read is authorized.");
77
+ }
78
+ export function taskRemoteDeliveryProofTask(task) {
79
+ return {
80
+ id: task.id,
81
+ status: task.status,
82
+ projectBindings: task.projectBindings,
83
+ ...(task.workspaceIdentity === undefined
84
+ ? {}
85
+ : { workspaceIdentity: task.workspaceIdentity }),
86
+ ...(task.completedAt === undefined ? {} : { completedAt: task.completedAt }),
87
+ ...(task.retiredAt === undefined ? {} : { retiredAt: task.retiredAt })
88
+ };
89
+ }
@@ -22,7 +22,6 @@ export const TASK_ACTIVATION_EVENT = Object.freeze({
22
22
  adopted: "task.activation-adopted",
23
23
  failed: "task.activation-failed"
24
24
  });
25
- export const TASK_ACTIVATION_ORIGINS = Object.freeze(["explicit", "submit-develop"]);
26
25
  /**
27
26
  * The digest that decides whether a repeated requestId is the same request.
28
27
  *
@@ -64,7 +63,6 @@ export function createTaskActivationRequest(taskId, input, now) {
64
63
  partialResultRefs: []
65
64
  },
66
65
  startMode: input.startMode,
67
- ...(input.origin === undefined ? {} : { origin: input.origin }),
68
66
  ...(input.afterPlanningRun === undefined
69
67
  ? {}
70
68
  : { afterPlanningRun: input.afterPlanningRun }),
@@ -196,26 +194,6 @@ export function admitTaskActivationRequest(task, request, planningRunIsActive) {
196
194
  }
197
195
  return { disposition: "ready", request };
198
196
  }
199
- /**
200
- * Whether the Controller may continue (auto-adopt) a released request without an
201
- * explicit activation boundary call (task-32 §2.4).
202
- *
203
- * A deferred request already holds activation authority and is released by its
204
- * planning Turn ending, so it is adoptable regardless of origin. An immediate
205
- * request is auto-continued only when it carries a recognised provable origin:
206
- * an explicit activation action, or a develop submission the shared transaction
207
- * accepted while the Task was unplanned. A request with no origin — every one
208
- * migrated from before the field existed — is deliberately held back so an
209
- * upgrade cannot turn a historical pending request into a silent activation; it
210
- * still adopts through the explicit `yui task activate` boundary, which does not
211
- * consult origin. This replaces the old actor heuristic that both dropped legal
212
- * Operator/user immediate requests and could not distinguish provenance.
213
- */
214
- export function activationRequestIsControllerAdoptable(request) {
215
- if (request.startMode === "after-planning-turn")
216
- return true;
217
- return request.origin !== undefined;
218
- }
219
197
  /**
220
198
  * The durable terminal outcome for a requestId, read from the activation event
221
199
  * ledger.
@@ -258,9 +236,8 @@ export function validateTaskActivationRequest(request) {
258
236
  if (!["immediate", "after-planning-turn"].includes(request.startMode)) {
259
237
  throw new Error(`Activation start mode is invalid: ${String(request.startMode)}.`);
260
238
  }
261
- if (request.origin !== undefined
262
- && !TASK_ACTIVATION_ORIGINS.includes(request.origin)) {
263
- throw new Error(`Activation origin is invalid: ${String(request.origin)}.`);
239
+ if (Object.hasOwn(request, "origin")) {
240
+ throw new Error("Activation contains retired origin metadata; use the storage upgrade boundary.");
264
241
  }
265
242
  if ((request.startMode === "after-planning-turn")
266
243
  !== (request.afterPlanningRun !== undefined)) {
@@ -108,7 +108,6 @@ export function recordTaskActivationRequestInTransaction(tx, input, now) {
108
108
  actorId: input.actorId,
109
109
  authorityRef: input.authorityRef,
110
110
  startMode,
111
- ...(input.origin === undefined ? {} : { origin: input.origin }),
112
111
  ...(planningRun === undefined ? {} : { afterPlanningRun: planningRun }),
113
112
  environmentPlan: plan
114
113
  }, now);
@@ -118,7 +117,6 @@ export function recordTaskActivationRequestInTransaction(tx, input, now) {
118
117
  startMode: request.startMode,
119
118
  environmentPlan: describeEnvironmentPlan(request.environmentPlan),
120
119
  actor: request.operation.actorId,
121
- ...(request.origin === undefined ? {} : { origin: request.origin }),
122
120
  ...(request.afterPlanningRun === undefined
123
121
  ? {}
124
122
  : { afterPlanningRun: request.afterPlanningRun })
@@ -6,7 +6,6 @@ export const TASK_RECORD_ID_PREFIXES = {
6
6
  reviewRound: "review-round",
7
7
  changeSet: "change-set",
8
8
  integrationAttempt: "integration",
9
- integrationQueue: "integration-queue",
10
9
  durableJob: "job",
11
10
  message: "message",
12
11
  inputRequest: "input",