@zq-silk/yui 0.13.9 → 0.14.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 (229) hide show
  1. package/ARCHITECTURE.md +69 -428
  2. package/README.md +108 -298
  3. package/dist/agent/managedRuntimeEnvironment.js +2 -2
  4. package/dist/cli/commandCatalog.js +39 -77
  5. package/dist/cli/interactionCandidates.js +4 -4
  6. package/dist/cli/interactionPolicy.js +7 -10
  7. package/dist/cli/invocationRouter.js +1 -1
  8. package/dist/cli/updateCommand.js +6 -27
  9. package/dist/cli/updateOrchestrator.js +63 -484
  10. package/dist/cli/updatePorts.js +15 -333
  11. package/dist/cli/upgradeCommand.js +8 -65
  12. package/dist/cli.js +57 -242
  13. package/dist/commands/configCommands.js +11 -62
  14. package/dist/commands/executionAuditCommands.js +23 -23
  15. package/dist/commands/globalRoleCommands.js +2 -7
  16. package/dist/commands/jobCommands.js +1 -4
  17. package/dist/commands/projectCommands.js +5 -5
  18. package/dist/commands/releaseCommands.js +3 -10
  19. package/dist/commands/resourcesCommands.js +2 -2
  20. package/dist/commands/sessionCommands.js +2 -2
  21. package/dist/commands/taskActor.js +31 -39
  22. package/dist/commands/taskChangeSetCommands.js +5 -12
  23. package/dist/commands/taskCommands.js +464 -1249
  24. package/dist/commands/taskContextCommand.js +35 -36
  25. package/dist/commands/taskExecutionCommands.js +33 -46
  26. package/dist/commands/taskInputCommands.js +20 -42
  27. package/dist/commands/taskNextActionCommand.js +9 -9
  28. package/dist/commands/taskOverviewCommand.js +56 -95
  29. package/dist/commands/taskRoleRuntimeStatus.js +77 -107
  30. package/dist/commands/taskUpstreamCommands.js +3 -3
  31. package/dist/commands/taskWorkspaceCommands.js +7 -79
  32. package/dist/commands/telemetryCommands.js +32 -124
  33. package/dist/commands/workflowCommands.js +3 -3
  34. package/dist/completion/fileCompletionManager.js +1 -1
  35. package/dist/config/configCatalog.js +4 -6
  36. package/dist/config/yuiConfig.js +6 -43
  37. package/dist/context/dispatchContext.js +14 -30
  38. package/dist/context/roleSessionContext.js +2 -2
  39. package/dist/context/sessionBootstrapManifest.js +2 -2
  40. package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
  41. package/dist/context/turnInputContract.js +204 -0
  42. package/dist/context/wakeNotification.js +2 -2
  43. package/dist/controller/agentRuntimeObserver.js +18 -18
  44. package/dist/controller/clientRuntime.js +13 -20
  45. package/dist/controller/controller.js +89 -116
  46. package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
  47. package/dist/controller/jobControl.js +17 -17
  48. package/dist/controller/resourceInventory.js +6 -6
  49. package/dist/controller/resourceInventoryLinux.js +38 -59
  50. package/dist/controller/resourceInventoryRpc.js +3 -3
  51. package/dist/controller/resourceInventoryWorker.js +1 -1
  52. package/dist/controller/runtime.js +46 -53
  53. package/dist/controller/runtimeEventInbox.js +23 -31
  54. package/dist/controller/runtimeEventProcessor.js +15 -15
  55. package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
  56. package/dist/controller/runtimeLaunchCoordinator.js +3 -3
  57. package/dist/controller/runtimeObservationHook.js +11 -8
  58. package/dist/controller/sessionNotify.js +11 -11
  59. package/dist/controller/structuredProviderObservation.js +89 -16
  60. package/dist/coordination/workMailbox.js +309 -579
  61. package/dist/coordination/workMailboxQueue.js +5 -6
  62. package/dist/core/controllerClient.js +1 -91
  63. package/dist/core/controllerServer.js +3 -6
  64. package/dist/doctor/doctor.js +51 -314
  65. package/dist/execution/candidateConvergence.js +3 -3
  66. package/dist/execution/executionGroup.js +32 -33
  67. package/dist/execution/executionHealth.js +36 -38
  68. package/dist/execution/resourceBroker.js +12 -12
  69. package/dist/executor/agentExecutor.js +30 -265
  70. package/dist/executor/effectiveLaunch.js +9 -19
  71. package/dist/executor/executorRegistry.js +43 -17
  72. package/dist/executor/fileRoleLaunchPlanner.js +56 -56
  73. package/dist/executor/launchPlan.js +3 -3
  74. package/dist/executor/workspacePreflightClassification.js +16 -16
  75. package/dist/grant/capabilityGrant.js +20 -25
  76. package/dist/input/inputRequest.js +12 -12
  77. package/dist/integration/changeSet.js +9 -13
  78. package/dist/integration/changeSetManifest.js +1 -1
  79. package/dist/integration/gitIntegrationService.js +2 -2
  80. package/dist/integration/integrationQueueService.js +5 -21
  81. package/dist/integration/overlapDiagnostics.js +2 -2
  82. package/dist/interaction/operatorPresentation.js +1 -1
  83. package/dist/job/jobRunner.js +1 -1
  84. package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
  85. package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
  86. package/dist/message/message.js +6 -6
  87. package/dist/observability/executionAudit.js +74 -86
  88. package/dist/observability/faultClassification.js +7 -24
  89. package/dist/observability/orchestrationMetrics.js +5 -5
  90. package/dist/observability/runtimeIdentity.js +34 -101
  91. package/dist/profile/agentProfile.js +1 -1
  92. package/dist/release/cliHomeReleaseFence.js +3 -3
  93. package/dist/release/releaseWorkflowEngine.js +6 -10
  94. package/dist/release/releaseWorkflowPorts.js +2 -2
  95. package/dist/release/workflowFileLock.js +1 -1
  96. package/dist/repository/checkoutSwap.js +1 -1
  97. package/dist/repository/gitWorkspace.js +0 -13
  98. package/dist/repository/project.js +1 -1
  99. package/dist/repository/projectMaintenanceLock.js +1 -2
  100. package/dist/repository/taskBaseFreshness.js +13 -13
  101. package/dist/repository/taskWorkspaceCoordinator.js +21 -25
  102. package/dist/repository/taskWorkspaceIdentity.js +8 -21
  103. package/dist/repository/taskWorkspacePreparer.js +63 -620
  104. package/dist/resources/autoResourceGc.js +3 -3
  105. package/dist/resources/liveReferences.js +1 -1
  106. package/dist/resources/resourceGc.js +1 -1
  107. package/dist/resources/sqliteResourceRegistry.js +1 -1
  108. package/dist/review/reviewDecision.js +7 -7
  109. package/dist/review/reviewFindingLedger.js +1 -1
  110. package/dist/review/reviewOutcomeClassifier.js +35 -50
  111. package/dist/review/reviewRound.js +14 -25
  112. package/dist/review/reviewerAvailability.js +4 -4
  113. package/dist/review/taskFinalReviewContractResolution.js +41 -0
  114. package/dist/role/role.js +6 -3
  115. package/dist/runtime/agentDriver.js +4 -0
  116. package/dist/runtime/agentHost.js +151 -36
  117. package/dist/runtime/builtinAgentDrivers.js +79 -2
  118. package/dist/runtime/codexAppServerRuntime.js +122 -0
  119. package/dist/runtime/continuationManager.js +3 -5
  120. package/dist/runtime/exactControlPlane.js +17 -42
  121. package/dist/runtime/firstProgressAdvisory.js +1 -1
  122. package/dist/runtime/index.js +2 -2
  123. package/dist/runtime/launchDiagnostics.js +2 -2
  124. package/dist/runtime/lifecycleReservation.js +4 -4
  125. package/dist/runtime/processExitObservation.js +1 -1
  126. package/dist/runtime/processExitOutbox.js +0 -32
  127. package/dist/runtime/promptEnvelope.js +9 -9
  128. package/dist/runtime/providerContinuation.js +2 -2
  129. package/dist/runtime/providerContinuationReconciliationService.js +2 -2
  130. package/dist/runtime/providerRuntimeIdentity.js +76 -24
  131. package/dist/runtime/recentTurnIds.js +38 -0
  132. package/dist/runtime/runtimeContinuationProjection.js +2 -2
  133. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  134. package/dist/runtime/runtimeObservation.js +58 -21
  135. package/dist/runtime/runtimeProjection.js +19 -27
  136. package/dist/runtime/sessionLaunchRequest.js +2 -2
  137. package/dist/runtime/structuredProviderHost.js +177 -12
  138. package/dist/runtime/tmuxAdapters.js +46 -11
  139. package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
  140. package/dist/scheduler/leaderWakeupProcessor.js +147 -445
  141. package/dist/scheduler/operatorEvent.js +4 -6
  142. package/dist/scheduler/resourceQueueProjection.js +71 -0
  143. package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
  144. package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
  145. package/dist/scheduler/taskExecutionProjection.js +99 -99
  146. package/dist/scheduler/taskObservabilityProjection.js +10 -10
  147. package/dist/scheduler/taskWake.js +4 -4
  148. package/dist/scheduler/wakeReason.js +6 -10
  149. package/dist/scheduler/wakeupQueue.js +0 -9
  150. package/dist/setup/setupCommand.js +2 -2
  151. package/dist/storage/currentTaskStore.js +46 -0
  152. package/dist/storage/persistenceWorker.js +1 -1
  153. package/dist/storage/sqliteSchema.js +81 -485
  154. package/dist/storage/sqliteStore.js +206 -365
  155. package/dist/storage/storageSchema.js +1 -15
  156. package/dist/storage/storageVersions.js +8 -9
  157. package/dist/storage/storeRpc.js +10 -34
  158. package/dist/storage/taskStore.js +63 -3415
  159. package/dist/storage/upgrade/recordVersions.js +55 -149
  160. package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
  161. package/dist/task/completionReadiness.js +5 -5
  162. package/dist/task/deliveryGuard.js +10 -10
  163. package/dist/task/nextAction.js +74 -77
  164. package/dist/task/task.js +2 -4
  165. package/dist/task/taskRecordReference.js +3 -3
  166. package/dist/task/taskRecordRetirement.js +1 -1
  167. package/dist/telemetry/sqliteTelemetryStore.js +53 -53
  168. package/dist/telemetry/telemetryConfig.js +14 -14
  169. package/dist/telemetry/telemetryWiring.js +8 -14
  170. package/dist/turn/turn.js +356 -0
  171. package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
  172. package/dist/verification/gateArtifactStore.js +2 -2
  173. package/dist/web/assets/client/app.js +1 -1
  174. package/dist/web/assets/client/components.js +29 -54
  175. package/dist/web/assets/client/i18n.js +17 -37
  176. package/dist/web/assets/client/view.js +37 -37
  177. package/dist/web/assets/shell.js +1 -1
  178. package/dist/web/assets/styles/cards.js +5 -5
  179. package/dist/web/assets/styles/widgets.js +1 -2
  180. package/dist/web/webSnapshot.js +65 -60
  181. package/dist/workItem/workItem.js +11 -11
  182. package/dist/workspace/workItemChangeSetManager.js +1 -1
  183. package/docs/task-local-identity.md +5 -5
  184. package/i18n/README.zh-CN.md +41 -54
  185. package/package.json +1 -1
  186. package/skills/yui-leader/SKILL.md +85 -83
  187. package/skills/yui-operator/SKILL.md +16 -16
  188. package/skills/yui-reviewer/SKILL.md +10 -10
  189. package/skills/yui-runtime/SKILL.md +17 -18
  190. package/skills/yui-worker/SKILL.md +16 -18
  191. package/dist/context/runContextContract.js +0 -162
  192. package/dist/executor/turnCompletion.js +0 -126
  193. package/dist/review/taskFinalReviewContractEvent.js +0 -1
  194. package/dist/review/taskFinalReviewContractRebind.js +0 -367
  195. package/dist/run/agentRun.js +0 -356
  196. package/dist/run/rejectedYieldAttempt.js +0 -221
  197. package/dist/run/runControlRequest.js +0 -50
  198. package/dist/run/yieldReceipt.js +0 -65
  199. package/dist/runtime/turnCompletion.js +0 -3
  200. package/dist/scheduler/actionability.js +0 -323
  201. package/dist/scheduler/activeRoleRunDelivery.js +0 -868
  202. package/dist/scheduler/activeTaskProgress.js +0 -126
  203. package/dist/storage/compatibleTaskStore.js +0 -248
  204. package/dist/storage/migration/baseline.js +0 -78
  205. package/dist/storage/migration/classifier.js +0 -51
  206. package/dist/storage/migration/compatibleCodec.js +0 -53
  207. package/dist/storage/migration/engine.js +0 -147
  208. package/dist/storage/migration/index.js +0 -33
  209. package/dist/storage/migration/planner.js +0 -154
  210. package/dist/storage/migration/productionRegistry.js +0 -3931
  211. package/dist/storage/migration/registry.js +0 -169
  212. package/dist/storage/migration/report.js +0 -54
  213. package/dist/storage/migration/types.js +0 -31
  214. package/dist/storage/upgrade/homeClassification.js +0 -353
  215. package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
  216. package/dist/storage/upgrade/migrationReceipt.js +0 -67
  217. package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
  218. package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
  219. package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
  220. package/dist/storage/upgrade/recordVersionScan.js +0 -176
  221. package/dist/storage/upgrade/sqliteFileSet.js +0 -50
  222. package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
  223. package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
  224. package/dist/storage/upgrade/sqliteStateMigration.js +0 -918
  225. package/dist/storage/upgrade/switchProgress.js +0 -80
  226. package/dist/storage/upgrade/upgradeReceipt.js +0 -161
  227. package/dist/storage/upgradeCoordination.js +0 -187
  228. package/dist/storage/upgradeFence.js +0 -366
  229. package/dist/telemetry/telemetryCompaction.js +0 -252
@@ -1,89 +1,17 @@
1
1
  import { usageError } from "../errors/cliError.js";
2
2
  import { createMilestone } from "../milestone/milestone.js";
3
- import { defaultTableWidth, renderTable } from "../output/table.js";
4
3
  import { runTaskCommand } from "./taskCommands.js";
5
4
  /**
6
- * Task workspace lifecycle commands that sit outside the sync task command
7
- * surface because they drive Git: controlled rebuild of a legacy Task
8
- * workspace, legacy ref history inspection/archival, and the
9
- * replacement-creating path for terminal Tasks.
5
+ * Task workspace lifecycle command that sits outside the sync task command
6
+ * surface because replacement preserves the terminal Task and creates a new
7
+ * current-contract Task.
10
8
  */
11
9
  export async function runTaskWorkspaceCommand(args, store, preparer, options = {}) {
12
10
  const [command, ...rest] = args;
13
- if (command === "rebuild")
14
- return rebuildTaskCommand(rest, preparer);
15
- if (command === "history")
16
- return historyCommand(rest, preparer);
11
+ void preparer;
17
12
  if (command === "replace")
18
13
  return replaceTaskCommand(rest, store, options);
19
- throw usageError("Unknown task workspace command. Available: yui task rebuild <task>, "
20
- + "yui task history list|archive [task], yui task replace <task>.");
21
- }
22
- async function rebuildTaskCommand(args, preparer) {
23
- const usage = "Task rebuild usage: yui task rebuild <task> [--latest].";
24
- const taskId = args[0];
25
- const options = new Set(args.slice(1));
26
- if (taskId === undefined
27
- || options.size !== args.length - 1
28
- || [...options].some((option) => option !== "--latest")) {
29
- throw usageError(usage);
30
- }
31
- const result = await preparer.rebuildTaskWorkspace(taskId, {
32
- latestRemote: options.has("--latest")
33
- });
34
- const archived = result.archived.length === 0
35
- ? "no legacy refs"
36
- : `${result.archived.length} legacy ref(s) archived`;
37
- const resumed = result.resumed ? " (resumed pending cleanup)" : "";
38
- return {
39
- output: `Rebuilt Task workspace ${result.task.id} at ${result.task.cwd ?? "its configured workspace"}: `
40
- + `${archived}${resumed}.`,
41
- data: {
42
- taskId: result.task.id,
43
- archived: result.archived,
44
- resumed: result.resumed,
45
- latestRemote: options.has("--latest")
46
- }
47
- };
48
- }
49
- async function historyCommand(args, preparer) {
50
- const usage = "Task history usage: yui task history list|archive [task].";
51
- const action = args[0];
52
- if (action !== "list" && action !== "archive")
53
- throw usageError(usage);
54
- const taskId = args[1];
55
- if (args.length > 2)
56
- throw usageError(usage);
57
- if (action === "list") {
58
- const refs = await preparer.listLegacyTaskRefs(taskId);
59
- if (refs.length === 0) {
60
- return { output: "No legacy Task refs.", data: { refs: [] } };
61
- }
62
- return {
63
- output: renderTable("Legacy Task refs", [
64
- { header: "Project", minWidth: 8, maxWidth: 24 },
65
- { header: "Task", minWidth: 8, maxWidth: 16 },
66
- { header: "Legacy ref", minWidth: 16, maxWidth: 64 }
67
- ], refs.map((entry) => [entry.projectId, entry.taskId, entry.ref]), defaultTableWidth()),
68
- data: { refs }
69
- };
70
- }
71
- const result = await preparer.archiveLegacyTaskRefs(taskId);
72
- const lines = [];
73
- if (result.archived.length > 0) {
74
- lines.push(`Archived ${result.archived.length} legacy ref(s):`);
75
- lines.push(...result.archived.map((entry) => ` ${entry}`));
76
- }
77
- if (result.refused.length > 0) {
78
- lines.push(`Refused ${result.refused.length} live ref(s) owned by an open Task:`);
79
- lines.push(...result.refused.map((entry) => ` ${entry}`));
80
- }
81
- if (lines.length === 0)
82
- lines.push("No legacy Task refs to archive.");
83
- return {
84
- output: lines.join("\n"),
85
- data: { archived: result.archived, refused: result.refused }
86
- };
14
+ throw usageError("Unknown task workspace command. Available: yui task replace <task>.");
87
15
  }
88
16
  /**
89
17
  * A terminal (retired/completed/archived) Task is never rewritten in place.
@@ -100,10 +28,10 @@ function replaceTaskCommand(args, store, options) {
100
28
  if (old === null)
101
29
  throw usageError(`Task not found: ${oldId}.`);
102
30
  if (old.status === "draft") {
103
- throw usageError(`Draft Task ${old.id} owns no workspace to replace or rebuild; activate it or retire it and create a new Draft.`);
31
+ throw usageError(`Draft Task ${old.id} owns no completed history to replace; activate it or retire it and create a new Draft.`);
104
32
  }
105
33
  if (old.status === "active") {
106
- throw usageError(`Active Task can be rebuilt instead of replaced: ${old.id}.`);
34
+ throw usageError(`Active Task cannot be replaced: ${old.id}.`);
107
35
  }
108
36
  let title = `Replaces ${old.id}: ${old.title}`;
109
37
  for (let index = 1; index < args.length; index += 1) {
@@ -1,13 +1,9 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
1
  import { join } from "node:path";
3
2
  import { usageError } from "../errors/cliError.js";
4
- import { STORAGE_SCHEMA_FILE } from "../storage/storageSchema.js";
5
3
  import { CURRENT_CONFIG_SCHEMA_VERSION } from "../storage/taskStore.js";
6
- import { openTaskStore, SqliteTaskStore } from "../storage/sqliteStore.js";
7
- import { COMMITTED_DATABASE_FILENAME } from "../storage/upgrade/sqliteStateMigration.js";
8
- import { DEFAULT_RUN_CAP, DEFAULT_TERMINAL_KEEP, resolveRunCap, resolveTerminalKeep } from "../telemetry/telemetryConfig.js";
4
+ import { CURRENT_DATABASE_FILENAME as COMMITTED_DATABASE_FILENAME } from "../storage/currentTaskStore.js";
5
+ import { DEFAULT_TERMINAL_KEEP, resolveTurnCap, resolveTerminalKeep } from "../telemetry/telemetryConfig.js";
9
6
  import { resolveTelemetryEnabled } from "../config/yuiConfig.js";
10
- import { applyTelemetryCompaction, planTelemetryCompaction } from "../telemetry/telemetryCompaction.js";
11
7
  import { SqliteTelemetryStore } from "../telemetry/sqliteTelemetryStore.js";
12
8
  /** Read the durable config, falling back to defaults when no store is available. */
13
9
  function storeConfig(options) {
@@ -22,16 +18,13 @@ export async function runTelemetryCommand(args, options) {
22
18
  return telemetryStatus(rest, options);
23
19
  if (command === "prune")
24
20
  return telemetryPrune(rest, options);
25
- if (command === "compact")
26
- return telemetryCompact(rest, options);
27
21
  if (command === "read")
28
22
  return telemetryRead(rest, options);
29
23
  throw usageError(command === undefined
30
- ? "Telemetry command is required: status, prune, compact, or read."
24
+ ? "Telemetry command is required: status, prune, or read."
31
25
  : `Unknown command: telemetry ${command}`, "yui telemetry status [--json]\n"
32
26
  + "yui telemetry prune [--task <id>] [--keep <n>] [--dry-run] [--json]\n"
33
- + "yui telemetry compact --from <home> --staged <dir> [--keep <n>] [--dry-run] [--json]\n"
34
- + "yui telemetry read --task <id> [--run <id>] [--aggregate] [--limit <n>] [--offset <n>]");
27
+ + "yui telemetry read --task <id> [--turn <id>] [--aggregate] [--limit <n>] [--offset <n>]");
35
28
  }
36
29
  // -- status ---------------------------------------------------------------------
37
30
  function telemetryStatus(args, options) {
@@ -40,7 +33,7 @@ function telemetryStatus(args, options) {
40
33
  const telemetry = new SqliteTelemetryStore(options.home, {
41
34
  mode,
42
35
  terminalKeep: resolveTerminalKeep(storeConfig(options).telemetryTerminalKeep),
43
- runCap: resolveRunCap(storeConfig(options).telemetryRunCap)
36
+ turnCap: resolveTurnCap(storeConfig(options).telemetryTurnCap)
44
37
  });
45
38
  try {
46
39
  const health = telemetry.health();
@@ -50,7 +43,7 @@ function telemetryStatus(args, options) {
50
43
  : store.listTasks().map((task) => ({
51
44
  taskId: task.id,
52
45
  rows: telemetry.count(task.id),
53
- runs: telemetry.listRunAggregates(task.id).length
46
+ turns: telemetry.listTurnAggregates(task.id).length
54
47
  }));
55
48
  const report = {
56
49
  mode,
@@ -61,7 +54,7 @@ function telemetryStatus(args, options) {
61
54
  lastError: health.lastError,
62
55
  totalRows: health.rows,
63
56
  terminalKeep: resolveTerminalKeep(storeConfig(options).telemetryTerminalKeep),
64
- runCap: resolveRunCap(storeConfig(options).telemetryRunCap),
57
+ turnCap: resolveTurnCap(storeConfig(options).telemetryTurnCap),
65
58
  tasks: perTask
66
59
  };
67
60
  if (options.json || flags.has("json"))
@@ -75,10 +68,10 @@ function telemetryStatus(args, options) {
75
68
  `Coalesced: ${health.coalesced}`,
76
69
  ...(health.lastError === null ? [] : [`Last error: ${health.lastError}`]),
77
70
  `Terminal keep: ${report.terminalKeep}`,
78
- `Run cap: ${report.runCap}`
71
+ `Turn cap: ${report.turnCap}`
79
72
  ];
80
73
  for (const task of perTask) {
81
- lines.push(` ${task.taskId}: ${task.rows} rows across ${task.runs} run generation(s)`);
74
+ lines.push(` ${task.taskId}: ${task.rows} rows across ${task.turns} Turn generation(s)`);
82
75
  }
83
76
  return lines.join("\n");
84
77
  }
@@ -92,12 +85,12 @@ function telemetryPrune(args, options) {
92
85
  const taskId = stringOption(args, "--task");
93
86
  const keep = integerOption(args, "--keep", DEFAULT_TERMINAL_KEEP);
94
87
  const dryRun = flags.has("dry-run");
95
- const cap = resolveRunCap(storeConfig(options).telemetryRunCap);
88
+ const cap = resolveTurnCap(storeConfig(options).telemetryTurnCap);
96
89
  const store = requireStore(options);
97
90
  const telemetry = new SqliteTelemetryStore(options.home, {
98
91
  mode: telemetryMode(storeConfig(options)),
99
92
  terminalKeep: keep,
100
- runCap: cap
93
+ turnCap: cap
101
94
  });
102
95
  try {
103
96
  const tasks = taskId === undefined
@@ -105,35 +98,35 @@ function telemetryPrune(args, options) {
105
98
  : [taskId];
106
99
  const report = [];
107
100
  for (const id of tasks) {
108
- const terminalRuns = new Set(store.listAgentRuns(id)
101
+ const terminalTurns = new Set(store.listTurns(id)
109
102
  .filter((run) => run.status !== "active")
110
103
  .map((run) => run.id));
111
104
  const entry = { taskId: id, terminalPruned: 0, activeCapped: 0, generations: [] };
112
- for (const aggregate of telemetry.listRunAggregates(id)) {
113
- if (terminalRuns.has(aggregate.runId)) {
114
- const before = telemetry.count(id, aggregate.runId);
105
+ for (const aggregate of telemetry.listTurnAggregates(id)) {
106
+ if (terminalTurns.has(aggregate.turnId)) {
107
+ const before = telemetry.count(id, aggregate.turnId);
115
108
  const deleted = dryRun
116
109
  ? Math.max(0, before - keep)
117
- : telemetry.pruneGeneration(aggregate.taskId, aggregate.roleName, aggregate.runId, aggregate.generation, keep);
110
+ : telemetry.pruneGeneration(aggregate.taskId, aggregate.roleName, aggregate.turnId, aggregate.generation, keep);
118
111
  entry.terminalPruned += deleted;
119
112
  entry.generations.push({
120
- runId: aggregate.runId,
113
+ turnId: aggregate.turnId,
121
114
  generation: aggregate.generation,
122
115
  kept: Math.min(before, keep),
123
116
  deleted
124
117
  });
125
118
  }
126
119
  }
127
- for (const run of store.listAgentRuns(id)) {
120
+ for (const run of store.listTurns(id)) {
128
121
  if (run.status !== "active")
129
122
  continue;
130
123
  const before = telemetry.count(id, run.id);
131
124
  if (before <= cap)
132
125
  continue;
133
- const deleted = dryRun ? before - cap : telemetry.capRun(id, run.id, cap);
126
+ const deleted = dryRun ? before - cap : telemetry.capTurn(id, run.id, cap);
134
127
  entry.activeCapped += deleted;
135
128
  entry.generations.push({
136
- runId: run.id,
129
+ turnId: run.id,
137
130
  generation: "*",
138
131
  kept: Math.min(before, cap),
139
132
  deleted
@@ -151,14 +144,14 @@ function telemetryPrune(args, options) {
151
144
  const lines = [
152
145
  `Telemetry prune (${dryRun ? "dry-run" : "applied"}):`,
153
146
  ` terminal generations pruned: ${totals.terminalPruned} row(s) (keep ${keep})`,
154
- ` active runs capped: ${totals.activeCapped} row(s) (cap ${cap})`
147
+ ` active Turns capped: ${totals.activeCapped} row(s) (cap ${cap})`
155
148
  ];
156
149
  for (const entry of report) {
157
150
  if (entry.generations.length === 0)
158
151
  continue;
159
152
  lines.push(` ${entry.taskId}:`);
160
153
  for (const generation of entry.generations) {
161
- lines.push(` ${generation.runId}/${generation.generation}: kept ${generation.kept}, deleted ${generation.deleted}`);
154
+ lines.push(` ${generation.turnId}/${generation.generation}: kept ${generation.kept}, deleted ${generation.deleted}`);
162
155
  }
163
156
  }
164
157
  return lines.join("\n");
@@ -167,105 +160,38 @@ function telemetryPrune(args, options) {
167
160
  void telemetry.close();
168
161
  }
169
162
  }
170
- // -- compact --------------------------------------------------------------------
171
- function telemetryCompact(args, options) {
172
- const flags = parseFlags(args, new Set(["dry-run", "json"]));
173
- const from = stringOption(args, "--from");
174
- const staged = stringOption(args, "--staged");
175
- const keep = integerOption(args, "--keep", DEFAULT_TERMINAL_KEEP);
176
- const dryRun = flags.has("dry-run");
177
- if (from === undefined || staged === undefined) {
178
- throw usageError("telemetry compact requires --from <home> and --staged <dir>.", "yui telemetry compact --from <home> --staged <dir> [--keep <n>] [--dry-run]");
179
- }
180
- const resolvedFrom = resolvePath(from);
181
- const resolvedStaged = resolvePath(staged);
182
- if (resolvedFrom === resolvedStaged) {
183
- throw usageError("--from and --staged must be different directories.");
184
- }
185
- if (!existsSync(join(resolvedFrom, STORAGE_SCHEMA_FILE))) {
186
- throw usageError(`--from is not a Yui Home (missing ${STORAGE_SCHEMA_FILE}): ${resolvedFrom}`);
187
- }
188
- if (existsSync(resolvedStaged) && dryRun === false) {
189
- throw usageError(`--staged already exists; refuse to overwrite: ${resolvedStaged}`);
190
- }
191
- // Database-only direction: compaction folds semantic progress into the
192
- // telemetry tables inside `yui.db`. A Home without a database has not
193
- // reached SQLite storage yet; migrate it first (yui upgrade) instead
194
- // of silently compacting a file-only copy that telemetry cannot join.
195
- if (!existsSync(join(resolvedFrom, COMMITTED_DATABASE_FILENAME))) {
196
- throw usageError(`--from is not a SQLite Home (missing ${COMMITTED_DATABASE_FILENAME}): ${resolvedFrom}. `
197
- + "Migrate it to the database backend before compaction.");
198
- }
199
- const backend = "sqlite";
200
- mkdirSync(resolvedStaged, { recursive: true });
201
- copyStoreFiles(resolvedFrom, resolvedStaged);
202
- const store = openTaskStore(resolvedStaged, backend);
203
- const telemetry = new SqliteTelemetryStore(resolvedStaged, {
204
- mode: "on",
205
- terminalKeep: keep,
206
- runCap: DEFAULT_RUN_CAP
207
- });
208
- try {
209
- const plan = planTelemetryCompaction(store, { terminalKeep: keep });
210
- const receipt = applyTelemetryCompaction(store, telemetry, plan, {
211
- dryRun,
212
- source: resolvedFrom,
213
- terminalKeep: keep
214
- });
215
- writeFileSync(join(resolvedStaged, "telemetry-compaction.json"), JSON.stringify(receipt, null, 2) + "\n");
216
- if (options.json || flags.has("json"))
217
- return JSON.stringify({ staged: resolvedStaged, receipt }, null, 2);
218
- return [
219
- `Telemetry compaction (${dryRun ? "dry-run" : "applied"}) on staged copy:`,
220
- ` staged: ${resolvedStaged}`,
221
- ` backend: ${backend}`,
222
- ` tasks: ${receipt.totals.tasks}`,
223
- ` progress: ${receipt.totals.progressEvents} event(s) across ${receipt.totals.generations} generation(s)`,
224
- ` sidecar rows: ${receipt.totals.telemetryRows} (window ${keep}/generation)`,
225
- ` receipt: ${join(resolvedStaged, "telemetry-compaction.json")}`,
226
- dryRun
227
- ? "Dry-run made no changes. Re-run without --dry-run, then promote the staged Home after verifying the receipt."
228
- : "Applied. Promote the staged Home only after verifying the receipt; the original Home is unchanged."
229
- ].join("\n");
230
- }
231
- finally {
232
- void telemetry.close();
233
- if (store instanceof SqliteTaskStore)
234
- store.close();
235
- }
236
- }
237
163
  // -- read -----------------------------------------------------------------------
238
164
  function telemetryRead(args, options) {
239
165
  const flags = parseFlags(args, new Set(["aggregate", "json"]));
240
166
  const taskId = stringOption(args, "--task");
241
167
  if (taskId === undefined) {
242
- throw usageError("telemetry read requires --task <id>.", "yui telemetry read --task <id> [--run <id>] [--aggregate]");
168
+ throw usageError("telemetry read requires --task <id>.", "yui telemetry read --task <id> [--turn <id>] [--aggregate]");
243
169
  }
244
- const runId = stringOption(args, "--run");
170
+ const turnId = stringOption(args, "--turn");
245
171
  const limit = integerOption(args, "--limit", 100);
246
172
  const offset = integerOption(args, "--offset", 0);
247
173
  const telemetry = new SqliteTelemetryStore(options.home, {
248
174
  mode: telemetryMode(storeConfig(options)),
249
175
  terminalKeep: resolveTerminalKeep(storeConfig(options).telemetryTerminalKeep),
250
- runCap: resolveRunCap(storeConfig(options).telemetryRunCap)
176
+ turnCap: resolveTurnCap(storeConfig(options).telemetryTurnCap)
251
177
  });
252
178
  try {
253
179
  if (flags.has("aggregate")) {
254
- if (runId === undefined) {
255
- const aggregates = telemetry.listRunAggregates(taskId);
180
+ if (turnId === undefined) {
181
+ const aggregates = telemetry.listTurnAggregates(taskId);
256
182
  if (options.json || flags.has("json"))
257
183
  return JSON.stringify(aggregates, null, 2);
258
184
  return aggregates.map((aggregate) => formatAggregate(aggregate)).join("\n") || "(no telemetry)";
259
185
  }
260
- const aggregate = telemetry.aggregate(taskId, runId);
186
+ const aggregate = telemetry.aggregate(taskId, turnId);
261
187
  if (options.json || flags.has("json"))
262
188
  return JSON.stringify(aggregate, null, 2);
263
- return aggregate === null ? "(no telemetry for this Run)" : formatAggregate(aggregate);
189
+ return aggregate === null ? "(no telemetry for this Turn)" : formatAggregate(aggregate);
264
190
  }
265
- const page = telemetry.list(taskId, runId, { limit, offset });
191
+ const page = telemetry.list(taskId, turnId, { limit, offset });
266
192
  if (options.json || flags.has("json"))
267
193
  return JSON.stringify(page, null, 2);
268
- const lines = page.items.map((entry) => `${entry.receivedAt} ${entry.runId}/${entry.generation}/${entry.progressId}`
194
+ const lines = page.items.map((entry) => `${entry.receivedAt} ${entry.turnId}/${entry.generation}/${entry.progressId}`
269
195
  + `${entry.sequence === undefined ? "" : ` seq=${entry.sequence}`}`);
270
196
  if (page.nextOffset !== null)
271
197
  lines.push(`(next offset: ${page.nextOffset})`);
@@ -282,24 +208,6 @@ function requireStore(options) {
282
208
  }
283
209
  return options.store;
284
210
  }
285
- function resolvePath(value) {
286
- return value.startsWith("/") ? value : join(process.cwd(), value);
287
- }
288
- function copyStoreFiles(from, staged) {
289
- for (const filename of [
290
- COMMITTED_DATABASE_FILENAME,
291
- `${COMMITTED_DATABASE_FILENAME}-wal`,
292
- `${COMMITTED_DATABASE_FILENAME}-shm`
293
- ]) {
294
- const source = join(from, filename);
295
- if (existsSync(source))
296
- copyFile(source, join(staged, filename));
297
- }
298
- copyFile(join(from, STORAGE_SCHEMA_FILE), join(staged, STORAGE_SCHEMA_FILE));
299
- }
300
- function copyFile(source, destination) {
301
- writeFileSync(destination, readFileSync(source));
302
- }
303
211
  function parseFlags(args, known) {
304
212
  const flags = new Set();
305
213
  for (const arg of args) {
@@ -332,5 +240,5 @@ function integerOption(args, name, fallback) {
332
240
  return value;
333
241
  }
334
242
  function formatAggregate(aggregate) {
335
- return `${aggregate.runId}/${aggregate.generation}: count=${aggregate.count} first=${aggregate.firstAt} last=${aggregate.lastAt} maxSequence=${aggregate.maxSequence === null ? "-" : aggregate.maxSequence} errors=${aggregate.errorCount}`;
243
+ return `${aggregate.turnId}/${aggregate.generation}: count=${aggregate.count} first=${aggregate.firstAt} last=${aggregate.lastAt} maxSequence=${aggregate.maxSequence === null ? "-" : aggregate.maxSequence} errors=${aggregate.errorCount}`;
336
244
  }
@@ -61,9 +61,9 @@ export async function runWorkflowCommandAsync(args, store, options) {
61
61
  // first transition or calls an external system. A run that is killed,
62
62
  // crashes, or whose engine rethrows after this point can never leave
63
63
  // mutation or effect evidence without an audit record saying the run was
64
- // attempted. FileTaskStore transactions are synchronous, so the async
65
- // engine run cannot join this transaction; committing the intent first is
66
- // what makes the trail crash-safe across the whole run.
64
+ // attempted. The async engine run cannot join this synchronous transaction;
65
+ // committing the intent first is
66
+ // what makes the trail crash-safe across the whole turn.
67
67
  const intentNow = clock(options);
68
68
  store.transaction((tx) => {
69
69
  recordTaskEvent(tx, taskId, "release-workflow.run-started", {
@@ -1,6 +1,6 @@
1
1
  import { installCompletion } from "./completionInstaller.js";
2
2
  import { COMPLETION_SHELLS, completionActivationIsCurrent, completionScriptIsCurrent, currentCompletionShell, suggestedCompletionInstallation } from "./completionState.js";
3
- /** FileTaskStore-backed completion port used by the interactive CLI wizard. */
3
+ /** Durable completion port used by the interactive CLI wizard. */
4
4
  export class FileCompletionManager {
5
5
  #store;
6
6
  #env;
@@ -1,5 +1,4 @@
1
- import { MAX_RUN_CAP } from "../telemetry/telemetryConfig.js";
2
- import { MAX_CONTEXT_BUDGET_TOKENS, MIN_CONTEXT_BUDGET_TOKENS } from "./yuiConfig.js";
1
+ import { MAX_TURN_CAP } from "../telemetry/telemetryConfig.js";
3
2
  export const CONFIG_DOMAINS = ["system", "runtime", "workflow", "resources", "tools"];
4
3
  /**
5
4
  * Public durable configuration contract. CLI help, completion, config show,
@@ -16,8 +15,7 @@ export const CONFIG_DEFINITIONS = Object.freeze([
16
15
  { key: "agent-launch-inactivity-timeout-seconds", domain: "runtime", property: "agentLaunchInactivityTimeoutSeconds", label: "Agent launch inactivity timeout", summary: "Maximum launch silence before startup fails, 15-3600 seconds (default: 300).", takesEffect: "After the Controller restarts." },
17
16
  { key: "delivery-timeout-seconds", domain: "runtime", property: "deliveryTimeoutSeconds", label: "Delivery timeout", summary: "Total control-plane delivery retry budget, 5-600 seconds (default: 120).", takesEffect: "After the Controller restarts; internal retry cadence remains automatic." },
18
17
  { key: "leader-next-action", domain: "workflow", property: "leaderNextActionMode", label: "Leader next-action mode", summary: "Leader next-action mode: display, warn, or enforce (default: display).", takesEffect: "The next Leader next-action projection or gate." },
19
- { key: "leader-semantic-budget-turns", domain: "workflow", property: "leaderSemanticBudgetTurns", label: "Leader semantic budget", summary: "Consecutive yielded Leader turns without durable delivery progress before warning, 1-20 (default: 3).", takesEffect: "The next Leader delivery guard evaluation." },
20
- { key: "context-budget", domain: "workflow", property: "contextBudget", label: "Legacy context budget (inactive)", summary: `Compatibility-only soft and hard values in ${MIN_CONTEXT_BUDGET_TOKENS}-${MAX_CONTEXT_BUDGET_TOKENS}; they are parsed but never control Session or workflow behavior.`, takesEffect: "No runtime effect; Session Token metrics are read-only observations." },
18
+ { key: "leader-semantic-budget-turns", domain: "workflow", property: "leaderSemanticBudgetTurns", label: "Leader semantic budget", summary: "Consecutive completed Leader turns without durable delivery progress before warning, 1-20 (default: 3).", takesEffect: "The next Leader delivery guard evaluation." },
21
19
  { key: "review", domain: "workflow", property: "review", label: "Review", summary: "Optional global WorkItem review rule: a configured Role plus always, leader, or final trigger and optional finding-ledger behavior. Setup leaves it disabled so the Leader may review directly or delegate selectively.", takesEffect: "The next Candidate snapshot; in-flight Candidates and ReviewRounds keep their policy." },
22
20
  { key: "resources-gc-mode", domain: "resources", property: "resourcesGcMode", label: "Resources GC mode", summary: "Resource GC mode: report or quarantine (default: report).", takesEffect: "The next resource GC operation." },
23
21
  { key: "resources-gc-auto-quarantine", domain: "resources", property: "resourcesGcAutoQuarantine", label: "Resources GC auto-quarantine", summary: "Automatically quarantine eligible terminal Task resources (default: false).", takesEffect: "The next eligible automatic resource GC operation." },
@@ -25,8 +23,8 @@ export const CONFIG_DEFINITIONS = Object.freeze([
25
23
  { key: "tmux-bin", domain: "tools", property: "tmuxBin", label: "Tmux bin", summary: "Command or path to the tmux binary (default: tmux).", takesEffect: "The next CLI-owned tmux invocation; restart the Controller for Controller-owned launches." },
26
24
  { key: "tmux-history-limit", domain: "tools", property: "tmuxHistoryLimit", label: "Tmux history limit", summary: "History lines retained for newly created tmux sessions, 1000-1000000 (default: 100000).", takesEffect: "New tmux sessions; existing sessions report drift until recreated." },
27
25
  { key: "telemetry-enabled", domain: "tools", property: "telemetryEnabled", label: "Diagnostic telemetry", summary: "Enable the optional SQLite diagnostic telemetry projection (default: false); requires a SQLite Home.", takesEffect: "Standalone telemetry commands immediately; scheduler writes after Controller restart." },
28
- { key: "telemetry-terminal-keep", domain: "tools", property: "telemetryTerminalKeep", label: "Telemetry terminal keep", summary: "Positive-integer rows retained per terminal Run generation (default: 200).", takesEffect: "Explicit retention immediately; automatic retention after the Controller restarts." },
29
- { key: "telemetry-run-cap", domain: "tools", property: "telemetryRunCap", label: "Telemetry Run cap", summary: `Positive-integer maximum rows retained per Run, at most ${MAX_RUN_CAP} (default: 50000).`, takesEffect: "Explicit retention immediately; automatic write-time capping after the Controller restarts." }
26
+ { key: "telemetry-terminal-keep", domain: "tools", property: "telemetryTerminalKeep", label: "Telemetry terminal keep", summary: "Positive-integer rows retained per terminal Turn generation (default: 200).", takesEffect: "Explicit retention immediately; automatic retention after the Controller restarts." },
27
+ { key: "telemetry-turn-cap", domain: "tools", property: "telemetryTurnCap", label: "Telemetry Turn cap", summary: `Positive-integer maximum rows retained per Turn, at most ${MAX_TURN_CAP} (default: 50000).`, takesEffect: "Explicit retention immediately; automatic write-time capping after the Controller restarts." }
30
28
  ]);
31
29
  export const CONFIG_KEYS = Object.freeze(CONFIG_DEFINITIONS.map(({ key }) => key));
32
30
  export function configDefinitionsForDomain(domain) {
@@ -1,4 +1,4 @@
1
- import { DEFAULT_RUN_CAP, DEFAULT_TERMINAL_KEEP, MAX_RUN_CAP } from "../telemetry/telemetryConfig.js";
1
+ import { DEFAULT_TURN_CAP, DEFAULT_TERMINAL_KEEP, MAX_TURN_CAP } from "../telemetry/telemetryConfig.js";
2
2
  import { DEFAULT_RUNTIME_HEALTH_POLICY } from "../runtime/runtimeHealthPolicy.js";
3
3
  export const DEFAULT_RECONCILIATION_INTERVAL_SECONDS = 120;
4
4
  export const MIN_RECONCILIATION_INTERVAL_SECONDS = 5;
@@ -99,14 +99,14 @@ export function resolveTelemetryTerminalKeep(value) {
99
99
  }
100
100
  return value;
101
101
  }
102
- export function resolveTelemetryRunCap(value) {
102
+ export function resolveTelemetryTurnCap(value) {
103
103
  if (value === undefined || value === null)
104
- return DEFAULT_RUN_CAP;
104
+ return DEFAULT_TURN_CAP;
105
105
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) {
106
- throw new TypeError("telemetryRunCap must be a positive integer.");
106
+ throw new TypeError("telemetryTurnCap must be a positive integer.");
107
107
  }
108
- if (value > MAX_RUN_CAP) {
109
- throw new TypeError(`telemetryRunCap must not exceed ${MAX_RUN_CAP.toLocaleString("en-US")} (retention cannot be disabled).`);
108
+ if (value > MAX_TURN_CAP) {
109
+ throw new TypeError(`telemetryTurnCap must not exceed ${MAX_TURN_CAP.toLocaleString("en-US")} (retention cannot be disabled).`);
110
110
  }
111
111
  return value;
112
112
  }
@@ -147,43 +147,6 @@ export function resolveLeaderSemanticBudgetTurns(value) {
147
147
  export function resolveTmuxHistoryLimit(value) {
148
148
  return resolveBoundedPositiveInteger(value, DEFAULT_TMUX_HISTORY_LIMIT, 1_000, 1_000_000, "tmuxHistoryLimit");
149
149
  }
150
- /**
151
- * Compatibility parser for the retired context-budget setting. Existing
152
- * Homes may retain these values, but no runtime, scheduler, or lifecycle path
153
- * consumes them. Session Token metrics are an independent read-only view.
154
- */
155
- export const DEFAULT_CONTEXT_SOFT_TOKENS = 100_000;
156
- export const DEFAULT_CONTEXT_HARD_TOKENS = 120_000;
157
- export const MIN_CONTEXT_BUDGET_TOKENS = 1_000;
158
- export const MAX_CONTEXT_BUDGET_TOKENS = 1_000_000;
159
- function resolveContextBudgetToken(value, label) {
160
- if (typeof value !== "number" || !Number.isSafeInteger(value)) {
161
- throw new TypeError(`${label} must be a safe integer.`);
162
- }
163
- if (value < MIN_CONTEXT_BUDGET_TOKENS || value > MAX_CONTEXT_BUDGET_TOKENS) {
164
- throw new TypeError(`${label} must be between ${MIN_CONTEXT_BUDGET_TOKENS} and ${MAX_CONTEXT_BUDGET_TOKENS}.`);
165
- }
166
- return value;
167
- }
168
- export function resolveContextBudget(configured) {
169
- if (configured === undefined || configured === null) {
170
- return { softTokens: DEFAULT_CONTEXT_SOFT_TOKENS, hardTokens: DEFAULT_CONTEXT_HARD_TOKENS };
171
- }
172
- if (typeof configured !== "object" || Array.isArray(configured)) {
173
- throw new TypeError("contextBudget must be an object.");
174
- }
175
- const record = configured;
176
- const softTokens = record.softTokens === undefined
177
- ? DEFAULT_CONTEXT_SOFT_TOKENS
178
- : resolveContextBudgetToken(record.softTokens, "contextBudget.softTokens");
179
- const hardTokens = record.hardTokens === undefined
180
- ? DEFAULT_CONTEXT_HARD_TOKENS
181
- : resolveContextBudgetToken(record.hardTokens, "contextBudget.hardTokens");
182
- if (softTokens >= hardTokens) {
183
- throw new TypeError("contextBudget.softTokens must be smaller than contextBudget.hardTokens.");
184
- }
185
- return { softTokens, hardTokens };
186
- }
187
150
  function resolveBoundedPositiveInteger(value, fallback, minimum, maximum, label) {
188
151
  if (value === undefined || value === null)
189
152
  return fallback;
@@ -1,7 +1,3 @@
1
- /** Compatibility entry point used by the restored Task workflow. */
2
- export function compileDispatchInput(_store, taskId, role, input, workContext = {}) {
3
- return buildRoleContext({ taskId, role, input, ...workContext });
4
- }
5
1
  export function buildRoleContext(context) {
6
2
  return context.role.name === "leader"
7
3
  ? buildLeaderContext(context)
@@ -13,40 +9,28 @@ export function buildLeaderContext(context) {
13
9
  export function buildWorkerContext(context) {
14
10
  return renderDispatchContext("worker", context);
15
11
  }
16
- const WORKER_RUN_COMPLETION_MARKER = "Yui Role Run completion requirement:";
17
- const WORKER_RUN_COMPLETION_REQUIREMENT = [
18
- WORKER_RUN_COMPLETION_MARKER,
19
- "Before ending, read the exact current Run ID from the managed first line and execute "
20
- + "`yui task run yield <current-run-id> --summary-file - <<'YUI_SUMMARY'` "
21
- + "followed by the outcome, evidence, and a closing `YUI_SUMMARY` line, "
22
- + "replacing the placeholder with that ID.",
12
+ const WORKER_TURN_COMPLETION_MARKER = "Yui Role Turn result requirement:";
13
+ const WORKER_TURN_COMPLETION_REQUIREMENT = [
14
+ WORKER_TURN_COMPLETION_MARKER,
15
+ "End the Provider turn with a truthful final report. Yui records that native turn result "
16
+ + "for the current Turn automatically; no completion command is required.",
23
17
  "If you cannot finally determine success, failure, completeness, or the correct "
24
18
  + "disposition, do not guess, silently stop, or hide uncertainty behind a success "
25
- + "summary. Use this exact yield path and label the handoff uncertain, incomplete, "
19
+ + "summary. Label the final report uncertain, incomplete, "
26
20
  + "blocked, or requiring Leader judgment.",
27
- "Report the most complete truthful evidence available and, when applicable: exact Run, "
21
+ "Report the most complete truthful evidence available and, when applicable: exact Turn, "
28
22
  + "WorkItem, and native Session identity; actions actually performed; changed paths "
29
23
  + "and commit/worktree state; checks actually run and their outcomes; provider, runtime, "
30
24
  + "or permission errors; the last confirmed lifecycle boundary; work not performed; "
31
25
  + "unresolved assumptions or decisions; residual risks; confidence; and bounded next options.",
32
- "Yield submits immutable Run evidence and a Candidate, or Review evidence only. It never "
33
- + "implies Leader acceptance, WorkItem completion, ChangeSet capture, Integration, or "
34
- + "Task completion. Review Runs report findings, verification gaps, and limits; the "
35
- + "Leader decides disposition.",
36
- "This exact control-plane permission does not grant repository writes, broad Bash, "
37
- + "external effects, or cross-Run control.",
38
- "If the exact yield is denied, do not retry, broaden permissions, use a wrapper, mutate "
39
- + "Yui state, or invent delivery evidence. Truthfully surface the blocker through the "
40
- + "supported provider failure boundary; there is no fallback protocol.",
41
- "Yielding closes the Run and hands the WorkItem to the Leader for acceptance; "
42
- + "a final response alone does neither.",
43
- "The yield command must be your final tool action. After it succeeds, stop immediately: "
44
- + "do not inspect, poll, accept, or perform any further work in the same native turn."
26
+ "The Provider turn ending closes only this Turn. It does not imply Leader acceptance, "
27
+ + "WorkItem completion, ChangeSet capture, Integration, or Task completion. Review Turns "
28
+ + "report findings, verification gaps, and limits; the Leader decides disposition."
45
29
  ].join("\n");
46
- export function ensureWorkerRunCompletionRequirement(input) {
47
- return input.endsWith(`\n\n${WORKER_RUN_COMPLETION_REQUIREMENT}`)
30
+ export function ensureWorkerTurnCompletionRequirement(input) {
31
+ return input.endsWith(`\n\n${WORKER_TURN_COMPLETION_REQUIREMENT}`)
48
32
  ? input
49
- : `${input}\n\n${WORKER_RUN_COMPLETION_REQUIREMENT}`;
33
+ : `${input}\n\n${WORKER_TURN_COMPLETION_REQUIREMENT}`;
50
34
  }
51
35
  function renderDispatchContext(kind, context) {
52
36
  const profile = context.role;
@@ -74,7 +58,7 @@ function renderDispatchContext(kind, context) {
74
58
  ].filter((section) => section !== null && section.length > 0)
75
59
  .join("\n\n");
76
60
  return kind === "worker"
77
- ? ensureWorkerRunCompletionRequirement(rendered)
61
+ ? ensureWorkerTurnCompletionRequirement(rendered)
78
62
  : rendered;
79
63
  }
80
64
  function renderContextLayers(context, kind) {
@@ -12,7 +12,7 @@ const BUILTIN_YUI_SKILLS = new Set([
12
12
  ]);
13
13
  /**
14
14
  * Compiles stable Role policy for an Agent-native instruction channel.
15
- * Dynamic wakeups and Run assignments deliberately remain outside this value.
15
+ * Dynamic wakeups and Turn assignments deliberately remain outside this value.
16
16
  */
17
17
  export function compileRoleSessionContext(yuiHome, role, owner, options = {}) {
18
18
  const kind = roleSessionKind(role, owner, options.purpose ?? "execution");
@@ -72,7 +72,7 @@ function renderRoleCore(kind, role, owner) {
72
72
  case "reviewer":
73
73
  return [
74
74
  `You are Yui review Role ${role.name} for Task ${owner.scope === "task" ? owner.taskId : role.name}.`,
75
- "Review only the exact frozen ReviewRound scope assigned to this Run.",
75
+ "Review only the exact frozen ReviewRound scope assigned to this Turn.",
76
76
  "Follow the injected yui-reviewer Skill while reviewing Yui work."
77
77
  ];
78
78
  case "worker":
@@ -133,8 +133,8 @@ export function materializeSessionBootstrap(input) {
133
133
  loadCommand: "\"$YUI_SESSION_CLI\" session context \"$YUI_ROLE\" --json"
134
134
  }
135
135
  : {
136
- loadCommand: "\"$YUI_SESSION_CLI\" task run context \"$YUI_TASK_ID/<run-id>\" --json",
137
- expandCommand: "\"$YUI_SESSION_CLI\" task run context expand \"$YUI_TASK_ID/<run-id>\" <ref-id> --store <store> --mode full --json"
136
+ loadCommand: "\"$YUI_SESSION_CLI\" task turn context \"$YUI_TASK_ID/<turn-id>\" --json",
137
+ expandCommand: "\"$YUI_SESSION_CLI\" task turn context expand \"$YUI_TASK_ID/<turn-id>\" <ref-id> --store <store> --mode full --json"
138
138
  }
139
139
  };
140
140
  const manifest = Object.freeze({ ...body, digest: digest(body) });