@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,12 +1,12 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import Database from "better-sqlite3";
4
- import { DEFAULT_RUN_CAP, DEFAULT_TERMINAL_KEEP } from "./telemetryConfig.js";
4
+ import { DEFAULT_TURN_CAP, DEFAULT_TERMINAL_KEEP } from "./telemetryConfig.js";
5
5
  import { migrateSqliteSchema } from "../storage/sqliteSchema.js";
6
- import { COMMITTED_DATABASE_FILENAME } from "../storage/upgrade/sqliteStateMigration.js";
6
+ import { CURRENT_DATABASE_FILENAME as COMMITTED_DATABASE_FILENAME } from "../storage/currentTaskStore.js";
7
7
  /**
8
8
  * Default sidecar implementation: the telemetry tables live inside the Home's
9
- * authoritative `yui.db` (schema migrations 1 and 5), so a database-only Home
9
+ * authoritative `yui.db`, so a Home has one durable database
10
10
  * has one file to manage, back up, and migrate. The store opens its own
11
11
  * connection to that file: the write path is a single serialized writer (the
12
12
  * "WAL worker") and stays isolated from the business store's connection.
@@ -16,9 +16,9 @@ import { COMMITTED_DATABASE_FILENAME } from "../storage/upgrade/sqliteStateMigra
16
16
  * batches. Queue overflow and database failures increment `dropped` and record
17
17
  * a health warning — the semantic lane is never affected.
18
18
  *
19
- * The telemetry tables are maintained by the centralized schema migrations:
20
- * `telemetry` (migration 1, §4.4) holds the bounded latest-per-key window and
21
- * `telemetry_aggregate` (migration 5) holds the authoritative per-Run/generation
19
+ * The telemetry tables are maintained by the centralized schema baseline:
20
+ * `telemetry` holds the bounded latest-per-key window and
21
+ * `telemetry_aggregate` holds the authoritative per-Turn/generation
22
22
  * summary, maintained by triggers so it survives window pruning.
23
23
  */
24
24
  const MAX_PAGE_LIMIT = 500;
@@ -26,7 +26,7 @@ export class SqliteTelemetryStore {
26
26
  mode;
27
27
  #path;
28
28
  #terminalKeep;
29
- #runCap;
29
+ #turnCap;
30
30
  #maxPending;
31
31
  #db = null;
32
32
  #failed = false;
@@ -41,7 +41,7 @@ export class SqliteTelemetryStore {
41
41
  this.mode = options.mode ?? "on";
42
42
  this.#path = join(home, COMMITTED_DATABASE_FILENAME);
43
43
  this.#terminalKeep = options.terminalKeep ?? DEFAULT_TERMINAL_KEEP;
44
- this.#runCap = options.runCap ?? DEFAULT_RUN_CAP;
44
+ this.#turnCap = options.turnCap ?? DEFAULT_TURN_CAP;
45
45
  this.#maxPending = options.maxPending ?? 10_000;
46
46
  }
47
47
  // -- TelemetrySink -------------------------------------------------------------
@@ -89,52 +89,52 @@ export class SqliteTelemetryStore {
89
89
  this.#db = null;
90
90
  }
91
91
  // -- TelemetryReader -----------------------------------------------------------
92
- count(taskId, runId) {
92
+ count(taskId, turnId) {
93
93
  const db = this.#ensureDb();
94
94
  if (db === null)
95
95
  return 0;
96
96
  if (taskId === undefined) {
97
97
  return db.prepare("SELECT COUNT(*) AS n FROM telemetry").get().n;
98
98
  }
99
- if (runId === undefined) {
99
+ if (turnId === undefined) {
100
100
  return db.prepare("SELECT COUNT(*) AS n FROM telemetry WHERE task_id = ?").get(taskId).n;
101
101
  }
102
- return db.prepare("SELECT COUNT(*) AS n FROM telemetry WHERE task_id = ? AND run_id = ?").get(taskId, runId).n;
102
+ return db.prepare("SELECT COUNT(*) AS n FROM telemetry WHERE task_id = ? AND turn_id = ?").get(taskId, turnId).n;
103
103
  }
104
- list(taskId, runId, page = { limit: 100, offset: 0 }) {
104
+ list(taskId, turnId, page = { limit: 100, offset: 0 }) {
105
105
  const db = this.#ensureDb();
106
106
  if (db === null)
107
107
  return { items: [], nextOffset: null };
108
108
  const limit = Math.min(Math.max(1, Math.trunc(page.limit)), MAX_PAGE_LIMIT);
109
109
  const offset = Math.max(0, Math.trunc(page.offset));
110
- const rows = runId === undefined
111
- ? db.prepare("SELECT task_id, role_name, run_id, generation, progress_id, sequence, payload, received_at FROM telemetry WHERE task_id = ? ORDER BY received_at, progress_id LIMIT ? OFFSET ?").all(taskId, limit, offset)
112
- : db.prepare("SELECT task_id, role_name, run_id, generation, progress_id, sequence, payload, received_at FROM telemetry WHERE task_id = ? AND run_id = ? ORDER BY received_at, progress_id LIMIT ? OFFSET ?").all(taskId, runId, limit, offset);
110
+ const rows = turnId === undefined
111
+ ? db.prepare("SELECT task_id, role_name, turn_id, generation, progress_id, sequence, payload, received_at FROM telemetry WHERE task_id = ? ORDER BY received_at, progress_id LIMIT ? OFFSET ?").all(taskId, limit, offset)
112
+ : db.prepare("SELECT task_id, role_name, turn_id, generation, progress_id, sequence, payload, received_at FROM telemetry WHERE task_id = ? AND turn_id = ? ORDER BY received_at, progress_id LIMIT ? OFFSET ?").all(taskId, turnId, limit, offset);
113
113
  const items = rows.map(rowToEntry);
114
- const total = this.count(taskId, runId);
114
+ const total = this.count(taskId, turnId);
115
115
  const nextOffset = offset + items.length < total ? offset + items.length : null;
116
116
  return { items, nextOffset };
117
117
  }
118
- aggregate(taskId, runId) {
118
+ aggregate(taskId, turnId) {
119
119
  const db = this.#ensureDb();
120
120
  if (db === null)
121
121
  return null;
122
- const rows = db.prepare("SELECT task_id, role_name, run_id, generation, first_at, last_at, count, max_sequence, error_count FROM telemetry_aggregate WHERE task_id = ? AND run_id = ?").all(taskId, runId);
122
+ const rows = db.prepare("SELECT task_id, role_name, turn_id, generation, first_at, last_at, count, max_sequence, error_count FROM telemetry_aggregate WHERE task_id = ? AND turn_id = ?").all(taskId, turnId);
123
123
  if (rows.length === 0)
124
124
  return null;
125
125
  return mergeAggregates(rows);
126
126
  }
127
- aggregateGeneration(taskId, roleName, runId, generation) {
127
+ aggregateGeneration(taskId, roleName, turnId, generation) {
128
128
  const db = this.#ensureDb();
129
129
  if (db === null)
130
130
  return null;
131
- const row = db.prepare("SELECT task_id, role_name, run_id, generation, first_at, last_at, count, max_sequence, error_count FROM telemetry_aggregate WHERE task_id = ? AND role_name = ? AND run_id = ? AND generation = ?").get(taskId, roleName, runId, generation);
131
+ const row = db.prepare("SELECT task_id, role_name, turn_id, generation, first_at, last_at, count, max_sequence, error_count FROM telemetry_aggregate WHERE task_id = ? AND role_name = ? AND turn_id = ? AND generation = ?").get(taskId, roleName, turnId, generation);
132
132
  if (row === undefined)
133
133
  return null;
134
134
  return {
135
135
  taskId: row.task_id,
136
136
  roleName: row.role_name,
137
- runId: row.run_id,
137
+ turnId: row.turn_id,
138
138
  generation: row.generation,
139
139
  firstAt: row.first_at,
140
140
  lastAt: row.last_at,
@@ -143,15 +143,15 @@ export class SqliteTelemetryStore {
143
143
  errorCount: row.error_count
144
144
  };
145
145
  }
146
- listRunAggregates(taskId) {
146
+ listTurnAggregates(taskId) {
147
147
  const db = this.#ensureDb();
148
148
  if (db === null)
149
149
  return [];
150
- const rows = db.prepare("SELECT task_id, role_name, run_id, generation, first_at, last_at, count, max_sequence, error_count FROM telemetry_aggregate WHERE task_id = ? ORDER BY run_id, generation").all(taskId);
150
+ const rows = db.prepare("SELECT task_id, role_name, turn_id, generation, first_at, last_at, count, max_sequence, error_count FROM telemetry_aggregate WHERE task_id = ? ORDER BY turn_id, generation").all(taskId);
151
151
  return rows.map((row) => ({
152
152
  taskId: row.task_id,
153
153
  roleName: row.role_name,
154
- runId: row.run_id,
154
+ turnId: row.turn_id,
155
155
  generation: row.generation,
156
156
  firstAt: row.first_at,
157
157
  lastAt: row.last_at,
@@ -164,32 +164,32 @@ export class SqliteTelemetryStore {
164
164
  return this.#applied;
165
165
  }
166
166
  // -- retention -----------------------------------------------------------------
167
- pruneGeneration(taskId, roleName, runId, generation, keep = this.#terminalKeep) {
167
+ pruneGeneration(taskId, roleName, turnId, generation, keep = this.#terminalKeep) {
168
168
  const db = this.#ensureDb();
169
169
  if (db === null)
170
170
  return 0;
171
171
  const result = db.prepare(`DELETE FROM telemetry
172
- WHERE task_id = ? AND role_name = ? AND run_id = ? AND generation = ?
173
- AND (task_id, role_name, run_id, generation, progress_id) NOT IN (
174
- SELECT task_id, role_name, run_id, generation, progress_id FROM telemetry
175
- WHERE task_id = ? AND role_name = ? AND run_id = ? AND generation = ?
172
+ WHERE task_id = ? AND role_name = ? AND turn_id = ? AND generation = ?
173
+ AND (task_id, role_name, turn_id, generation, progress_id) NOT IN (
174
+ SELECT task_id, role_name, turn_id, generation, progress_id FROM telemetry
175
+ WHERE task_id = ? AND role_name = ? AND turn_id = ? AND generation = ?
176
176
  ORDER BY COALESCE(sequence, -1) DESC, received_at DESC, progress_id ASC
177
177
  LIMIT ?
178
- )`).run(taskId, roleName, runId, generation, taskId, roleName, runId, generation, keep);
178
+ )`).run(taskId, roleName, turnId, generation, taskId, roleName, turnId, generation, keep);
179
179
  return result.changes;
180
180
  }
181
- capRun(taskId, runId, cap = this.#runCap) {
181
+ capTurn(taskId, turnId, cap = this.#turnCap) {
182
182
  const db = this.#ensureDb();
183
183
  if (db === null)
184
184
  return 0;
185
185
  const result = db.prepare(`DELETE FROM telemetry
186
- WHERE task_id = ? AND run_id = ?
187
- AND (task_id, role_name, run_id, generation, progress_id) NOT IN (
188
- SELECT task_id, role_name, run_id, generation, progress_id FROM telemetry
189
- WHERE task_id = ? AND run_id = ?
186
+ WHERE task_id = ? AND turn_id = ?
187
+ AND (task_id, role_name, turn_id, generation, progress_id) NOT IN (
188
+ SELECT task_id, role_name, turn_id, generation, progress_id FROM telemetry
189
+ WHERE task_id = ? AND turn_id = ?
190
190
  ORDER BY COALESCE(sequence, -1) DESC, received_at DESC, progress_id ASC
191
191
  LIMIT ?
192
- )`).run(taskId, runId, taskId, runId, cap);
192
+ )`).run(taskId, turnId, taskId, turnId, cap);
193
193
  return result.changes;
194
194
  }
195
195
  importGeneration(entries, aggregate) {
@@ -198,18 +198,18 @@ export class SqliteTelemetryStore {
198
198
  this.#dropped += entries.length;
199
199
  return;
200
200
  }
201
- const upsert = db.prepare(`INSERT INTO telemetry (task_id, role_name, run_id, generation, progress_id, sequence, payload, received_at)
201
+ const upsert = db.prepare(`INSERT INTO telemetry (task_id, role_name, turn_id, generation, progress_id, sequence, payload, received_at)
202
202
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
203
- ON CONFLICT(task_id, role_name, run_id, generation, progress_id) DO UPDATE SET
203
+ ON CONFLICT(task_id, role_name, turn_id, generation, progress_id) DO UPDATE SET
204
204
  sequence = excluded.sequence,
205
205
  payload = excluded.payload,
206
206
  received_at = excluded.received_at
207
207
  WHERE COALESCE(excluded.sequence, -1) > COALESCE(telemetry.sequence, -1)
208
208
  OR (excluded.sequence IS telemetry.sequence AND excluded.received_at >= telemetry.received_at)`);
209
209
  const upsertAggregate = db.prepare(`INSERT INTO telemetry_aggregate
210
- (task_id, role_name, run_id, generation, first_at, last_at, count, max_sequence, error_count, updated_at)
210
+ (task_id, role_name, turn_id, generation, first_at, last_at, count, max_sequence, error_count, updated_at)
211
211
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
212
- ON CONFLICT(task_id, role_name, run_id, generation) DO UPDATE SET
212
+ ON CONFLICT(task_id, role_name, turn_id, generation) DO UPDATE SET
213
213
  first_at = excluded.first_at,
214
214
  last_at = excluded.last_at,
215
215
  count = excluded.count,
@@ -218,9 +218,9 @@ export class SqliteTelemetryStore {
218
218
  updated_at = excluded.updated_at`);
219
219
  db.transaction(() => {
220
220
  for (const entry of entries) {
221
- upsert.run(entry.taskId, entry.roleName, entry.runId, entry.generation, entry.progressId, entry.sequence ?? null, JSON.stringify(entry.payload), entry.receivedAt);
221
+ upsert.run(entry.taskId, entry.roleName, entry.turnId, entry.generation, entry.progressId, entry.sequence ?? null, JSON.stringify(entry.payload), entry.receivedAt);
222
222
  }
223
- upsertAggregate.run(aggregate.taskId, aggregate.roleName, aggregate.runId, aggregate.generation, aggregate.firstAt, aggregate.lastAt, aggregate.count, aggregate.maxSequence, aggregate.errorCount, aggregate.lastAt);
223
+ upsertAggregate.run(aggregate.taskId, aggregate.roleName, aggregate.turnId, aggregate.generation, aggregate.firstAt, aggregate.lastAt, aggregate.count, aggregate.maxSequence, aggregate.errorCount, aggregate.lastAt);
224
224
  })();
225
225
  this.#applied += entries.length;
226
226
  }
@@ -277,26 +277,26 @@ export class SqliteTelemetryStore {
277
277
  }
278
278
  const batch = new Map(this.#pending);
279
279
  this.#pending.clear();
280
- const upsert = db.prepare(`INSERT INTO telemetry (task_id, role_name, run_id, generation, progress_id, sequence, payload, received_at)
280
+ const upsert = db.prepare(`INSERT INTO telemetry (task_id, role_name, turn_id, generation, progress_id, sequence, payload, received_at)
281
281
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
282
- ON CONFLICT(task_id, role_name, run_id, generation, progress_id) DO UPDATE SET
282
+ ON CONFLICT(task_id, role_name, turn_id, generation, progress_id) DO UPDATE SET
283
283
  sequence = excluded.sequence,
284
284
  payload = excluded.payload,
285
285
  received_at = excluded.received_at
286
286
  WHERE COALESCE(excluded.sequence, -1) > COALESCE(telemetry.sequence, -1)
287
287
  OR (excluded.sequence IS telemetry.sequence AND excluded.received_at >= telemetry.received_at)`);
288
288
  try {
289
- const touchedRuns = new Map();
289
+ const touchedTurns = new Map();
290
290
  db.transaction(() => {
291
291
  for (const entry of batch.values()) {
292
- upsert.run(entry.taskId, entry.roleName, entry.runId, entry.generation, entry.progressId, entry.sequence ?? null, JSON.stringify(entry.payload), entry.receivedAt);
293
- touchedRuns.set(`${entry.taskId}\0${entry.runId}`, {
292
+ upsert.run(entry.taskId, entry.roleName, entry.turnId, entry.generation, entry.progressId, entry.sequence ?? null, JSON.stringify(entry.payload), entry.receivedAt);
293
+ touchedTurns.set(`${entry.taskId}\0${entry.turnId}`, {
294
294
  taskId: entry.taskId,
295
- runId: entry.runId
295
+ turnId: entry.turnId
296
296
  });
297
297
  }
298
- for (const { taskId, runId } of touchedRuns.values()) {
299
- this.capRun(taskId, runId);
298
+ for (const { taskId, turnId } of touchedTurns.values()) {
299
+ this.capTurn(taskId, turnId);
300
300
  }
301
301
  })();
302
302
  this.#applied += batch.size;
@@ -308,7 +308,7 @@ export class SqliteTelemetryStore {
308
308
  }
309
309
  }
310
310
  function pendingKey(entry) {
311
- return `${entry.taskId}\u0000${entry.roleName}\u0000${entry.runId}\u0000${entry.generation}\u0000${entry.progressId}`;
311
+ return `${entry.taskId}\u0000${entry.roleName}\u0000${entry.turnId}\u0000${entry.generation}\u0000${entry.progressId}`;
312
312
  }
313
313
  /** True when `candidate` should replace `current` (sequence/receivedAt only move forward). */
314
314
  function isNewer(candidate, current) {
@@ -325,7 +325,7 @@ function rowToEntry(row) {
325
325
  return {
326
326
  taskId: row.task_id,
327
327
  roleName: row.role_name,
328
- runId: row.run_id,
328
+ turnId: row.turn_id,
329
329
  generation: row.generation,
330
330
  progressId: row.progress_id,
331
331
  ...(row.sequence === null ? {} : { sequence: row.sequence }),
@@ -356,7 +356,7 @@ function mergeAggregates(rows) {
356
356
  return {
357
357
  taskId: rows[0].task_id,
358
358
  roleName,
359
- runId: rows[0].run_id,
359
+ turnId: rows[0].turn_id,
360
360
  generation: "*",
361
361
  firstAt,
362
362
  lastAt,
@@ -6,34 +6,34 @@
6
6
  * never changes canonical runtime-state persistence. Retention defaults are
7
7
  * the schema's own constants (§4.4); the environment only overrides them.
8
8
  */
9
- import { TELEMETRY_KEEP_PER_GENERATION, TELEMETRY_RUN_CAP } from "../storage/sqliteSchema.js";
9
+ import { TELEMETRY_KEEP_PER_GENERATION, TELEMETRY_TURN_CAP } from "../storage/sqliteSchema.js";
10
10
  export const DEFAULT_TELEMETRY_MODE = "off";
11
- /** Terminal Run/generation progress rows retained after prune. */
11
+ /** Terminal Turn/generation progress rows retained after prune. */
12
12
  export const DEFAULT_TERMINAL_KEEP = TELEMETRY_KEEP_PER_GENERATION;
13
- /** Hard cap of progress rows per Run while it is still active. */
14
- export const DEFAULT_RUN_CAP = TELEMETRY_RUN_CAP;
13
+ /** Hard cap of progress rows per Turn while it is still active. */
14
+ export const DEFAULT_TURN_CAP = TELEMETRY_TURN_CAP;
15
15
  /**
16
- * Absolute ceiling for the configurable Run cap. Retention can be tuned but
16
+ * Absolute ceiling for the configurable Turn cap. Retention can be tuned but
17
17
  * never disabled: every Home keeps a computable upper bound on telemetry
18
- * rows (Tasks × Runs × cap).
18
+ * rows (Tasks × Turns × cap).
19
19
  */
20
- export const MAX_RUN_CAP = 10_000_000;
20
+ export const MAX_TURN_CAP = 10_000_000;
21
21
  /**
22
- * Resolve the terminal-Run retention window from the durable config value
22
+ * Resolve the terminal-Turn retention window from the durable config value
23
23
  * (default 200). Must be a positive integer.
24
24
  */
25
25
  export function resolveTerminalKeep(value) {
26
26
  return resolvePositiveInteger(value, DEFAULT_TERMINAL_KEEP, "telemetryTerminalKeep");
27
27
  }
28
28
  /**
29
- * Resolve the active-Run hard cap from the durable config value (default
30
- * 50,000). Must be a positive integer not exceeding {@link MAX_RUN_CAP};
29
+ * Resolve the active-Turn hard cap from the durable config value (default
30
+ * 50,000). Must be a positive integer not exceeding {@link MAX_TURN_CAP};
31
31
  * the cap cannot be disabled.
32
32
  */
33
- export function resolveRunCap(value) {
34
- const cap = resolvePositiveInteger(value, DEFAULT_RUN_CAP, "telemetryRunCap");
35
- if (cap > MAX_RUN_CAP) {
36
- throw new TypeError(`telemetryRunCap must not exceed ${MAX_RUN_CAP.toLocaleString("en-US")} (retention cannot be disabled).`);
33
+ export function resolveTurnCap(value) {
34
+ const cap = resolvePositiveInteger(value, DEFAULT_TURN_CAP, "telemetryTurnCap");
35
+ if (cap > MAX_TURN_CAP) {
36
+ throw new TypeError(`telemetryTurnCap must not exceed ${MAX_TURN_CAP.toLocaleString("en-US")} (retention cannot be disabled).`);
37
37
  }
38
38
  return cap;
39
39
  }
@@ -1,20 +1,14 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { resolveRunCap, resolveTerminalKeep } from "./telemetryConfig.js";
3
+ import { resolveTurnCap, resolveTerminalKeep } from "./telemetryConfig.js";
4
4
  import { resolveTelemetryEnabled } from "../config/yuiConfig.js";
5
5
  import { SqliteTelemetryStore } from "./sqliteTelemetryStore.js";
6
- import { COMMITTED_DATABASE_FILENAME } from "../storage/upgrade/sqliteStateMigration.js";
6
+ import { CURRENT_DATABASE_FILENAME as COMMITTED_DATABASE_FILENAME } from "../storage/currentTaskStore.js";
7
7
  /**
8
- * Open the telemetry sidecar for a Home, resolved from the durable Yui
9
- * config (default `legacy`). Returns null in legacy mode so callers keep the
10
- * exact master behavior and never touch the database.
11
- *
12
- * Telemetry lives in the Home's authoritative `yui.db`. A Home without a
13
- * database has not reached SQLite storage yet, so dual/bounded mode fails
14
- * closed at startup with a bounded diagnosis instead of silently creating an
15
- * empty database (which would corrupt Home classification). Once opened, the
16
- * store fails isolated: a broken sidecar only increments its dropped counter
17
- * and never blocks the semantic lane.
8
+ * Open optional telemetry from the current Home's authoritative `yui.db`.
9
+ * Disabled telemetry performs no database work. Once opened, telemetry fails
10
+ * isolated: a broken sink increments its dropped counter without blocking the
11
+ * semantic lane.
18
12
  */
19
13
  export function openSchedulerTelemetry(home, config) {
20
14
  if (!resolveTelemetryEnabled(config.telemetryEnabled))
@@ -23,12 +17,12 @@ export function openSchedulerTelemetry(home, config) {
23
17
  const dbPath = join(home, COMMITTED_DATABASE_FILENAME);
24
18
  if (!existsSync(dbPath)) {
25
19
  throw new Error(`telemetryEnabled=true requires SQLite storage, but ${dbPath} does not exist. `
26
- + "Migrate this Home to the database backend first (yui upgrade).");
20
+ + "The current Home is incomplete; preserve it for diagnosis and initialize a new Home.");
27
21
  }
28
22
  const store = new SqliteTelemetryStore(home, {
29
23
  mode,
30
24
  terminalKeep: resolveTerminalKeep(config.telemetryTerminalKeep),
31
- runCap: resolveRunCap(config.telemetryRunCap)
25
+ turnCap: resolveTurnCap(config.telemetryTurnCap)
32
26
  });
33
27
  return { mode, sink: store, reader: store, retention: store };
34
28
  }