@sema-agent/client-core 0.97.0 → 0.98.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 (281) hide show
  1. package/CHANGELOG.md +429 -0
  2. package/README.md +74 -36
  3. package/dist/adapt/arms.d.ts +1 -0
  4. package/dist/adapt/arms.js +128 -34
  5. package/dist/adapt/ids.d.ts +12 -1
  6. package/dist/adapt/ids.js +59 -8
  7. package/dist/adapt/instanceLedger.d.ts +50 -0
  8. package/dist/adapt/instanceLedger.js +147 -0
  9. package/dist/adapt/textStream.d.ts +1 -0
  10. package/dist/adapt/textStream.js +24 -7
  11. package/dist/adapt/toolCards.d.ts +27 -5
  12. package/dist/adapt/toolCards.js +39 -6
  13. package/dist/adapt/wireShapes.js +6 -2
  14. package/dist/adapt.d.ts +2 -0
  15. package/dist/adapt.js +8 -3
  16. package/dist/adapter/activeRunSelfHeal.d.ts +5 -0
  17. package/dist/adapter/activeRunSelfHeal.js +51 -28
  18. package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
  19. package/dist/adapter/downstream/eventToSdkMessage.js +27 -34
  20. package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
  21. package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
  22. package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
  23. package/dist/adapter/runStream.js +29 -13
  24. package/dist/adapter/types.d.ts +4 -4
  25. package/dist/agentSession/backgroundView.js +2 -1
  26. package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
  27. package/dist/agentSession/engineAgentRegistryRead.js +12 -13
  28. package/dist/agentsWireCaps.d.ts +8 -6
  29. package/dist/agentsWireCaps.js +177 -162
  30. package/dist/approvalDecidedByCapability.d.ts +0 -4
  31. package/dist/approvalDecidedByCapability.js +0 -6
  32. package/dist/approvalsStreamLiveCapability.d.ts +0 -4
  33. package/dist/approvalsStreamLiveCapability.js +0 -6
  34. package/dist/assistantInbox.d.ts +34 -0
  35. package/dist/assistantInbox.js +118 -0
  36. package/dist/centerWiringCapability.js +9 -1
  37. package/dist/clientSlice.d.ts +0 -9
  38. package/dist/clientSlice.js +0 -3
  39. package/dist/cloudConfigWireCaps.d.ts +4 -2
  40. package/dist/cloudConfigWireCaps.js +81 -61
  41. package/dist/compensations.js +1 -1
  42. package/dist/connectorStatus.d.ts +21 -0
  43. package/dist/connectorStatus.js +112 -0
  44. package/dist/controlRouter.d.ts +14 -1
  45. package/dist/controlRouter.js +68 -17
  46. package/dist/coreValuePorts.d.ts +3 -3
  47. package/dist/decideReceipt.d.ts +2 -2
  48. package/dist/decideReceipt.js +5 -2
  49. package/dist/declared/supportFloorDeclared.js +3 -3
  50. package/dist/deviceExecutorManagementCapability.d.ts +0 -4
  51. package/dist/deviceExecutorManagementCapability.js +0 -6
  52. package/dist/deviceRebind.d.ts +49 -1
  53. package/dist/deviceRebind.js +221 -3
  54. package/dist/displayUntrusted.d.ts +1 -0
  55. package/dist/displayUntrusted.js +250 -76
  56. package/dist/engineAgentAbsence.d.ts +1 -1
  57. package/dist/engineAgentPanelStore.d.ts +5 -4
  58. package/dist/engineAgentPanelStore.js +3 -12
  59. package/dist/engineCapReader.d.ts +0 -4
  60. package/dist/engineCapReader.js +1 -5
  61. package/dist/engineCapsCache.d.ts +4 -0
  62. package/dist/engineCapsCache.js +17 -12
  63. package/dist/engineClosedSets.d.ts +1 -0
  64. package/dist/engineClosedSets.js +4 -1
  65. package/dist/engineErrorCodes.d.ts +9 -2
  66. package/dist/engineErrorCodes.js +9 -1
  67. package/dist/engineIdentity.d.ts +1 -0
  68. package/dist/engineIdentity.js +8 -0
  69. package/dist/engineRowRef.d.ts +28 -0
  70. package/dist/engineRowRef.js +111 -0
  71. package/dist/engineSessionMessages.d.ts +67 -0
  72. package/dist/engineSessionMessages.js +364 -0
  73. package/dist/engineToolDirectory.d.ts +18 -0
  74. package/dist/engineToolDirectory.js +85 -0
  75. package/dist/engineUrl.d.ts +18 -0
  76. package/dist/engineUrl.js +52 -0
  77. package/dist/env/uiLanguage.d.ts +9 -0
  78. package/dist/env/uiLanguage.js +35 -0
  79. package/dist/eventLeg.d.ts +92 -0
  80. package/dist/eventLeg.js +285 -0
  81. package/dist/executionLaneCapability.d.ts +0 -4
  82. package/dist/executionLaneCapability.js +3 -16
  83. package/dist/fileHistoryCaptureCapability.d.ts +0 -4
  84. package/dist/fileHistoryCaptureCapability.js +5 -7
  85. package/dist/fleet/fleetLedger.d.ts +0 -3
  86. package/dist/fleet/fleetLedger.js +21 -36
  87. package/dist/fleet/fleetProjection.d.ts +2 -2
  88. package/dist/fleet/fleetProjection.js +10 -8
  89. package/dist/frameBinding.d.ts +5 -0
  90. package/dist/frameBinding.js +23 -0
  91. package/dist/gateFailureCodes.d.ts +2 -0
  92. package/dist/gateFailureCodes.js +15 -0
  93. package/dist/gateOutcome.d.ts +3 -1
  94. package/dist/gateOutcome.js +25 -6
  95. package/dist/gateVocabulary.d.ts +5 -0
  96. package/dist/gateVocabulary.js +64 -2
  97. package/dist/generated/engineAskFaceTables.js +2 -2
  98. package/dist/generated/engineFactTables.d.ts +6 -3
  99. package/dist/generated/engineFactTables.js +22 -4
  100. package/dist/generated/engineNoticeTables.js +9 -0
  101. package/dist/generated/toolNameTables.d.ts +1 -0
  102. package/dist/generated/toolNameTables.js +1 -0
  103. package/dist/hitl/allowRuleShadow.d.ts +6 -1
  104. package/dist/hitl/allowRuleShadow.js +21 -17
  105. package/dist/hitl/approvalCardReading.d.ts +15 -0
  106. package/dist/hitl/approvalCardReading.js +154 -0
  107. package/dist/hitl/approvalCardReasons.d.ts +13 -0
  108. package/dist/hitl/approvalCardReasons.js +120 -0
  109. package/dist/hitl/approvalHolds.d.ts +47 -15
  110. package/dist/hitl/approvalHolds.js +134 -28
  111. package/dist/hitl/approvalResolution.d.ts +51 -26
  112. package/dist/hitl/approvalResolution.js +86 -122
  113. package/dist/hitl/approvalsFeed.js +6 -18
  114. package/dist/hitl/askClassPair.d.ts +2 -0
  115. package/dist/hitl/askClassPair.js +1 -0
  116. package/dist/hitl/askGateWire.d.ts +20 -2
  117. package/dist/hitl/askGateWire.js +49 -1
  118. package/dist/hitl/askParkRowRouting.d.ts +5 -0
  119. package/dist/hitl/askParkRowRouting.js +32 -1
  120. package/dist/hitl/askSettlementLine.d.ts +18 -0
  121. package/dist/hitl/askSettlementLine.js +79 -0
  122. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  123. package/dist/hitl/automaticAnswerVerdict.js +21 -5
  124. package/dist/hitl/crashConverged.d.ts +11 -20
  125. package/dist/hitl/crashConverged.js +56 -0
  126. package/dist/hitl/crashConvergedNotice.d.ts +3 -1
  127. package/dist/hitl/crashConvergedNotice.js +48 -11
  128. package/dist/hitl/decisionConflict.js +3 -10
  129. package/dist/hitl/decisionRefusal.d.ts +40 -1
  130. package/dist/hitl/decisionRefusal.js +199 -42
  131. package/dist/hitl/frameRouter.d.ts +5 -2
  132. package/dist/hitl/frameRouter.js +20 -16
  133. package/dist/hitl/gateLedger.d.ts +2 -0
  134. package/dist/hitl/gateLedger.js +50 -13
  135. package/dist/hitl/hitlBridge.d.ts +1 -2
  136. package/dist/hitl/hitlBridge.js +10 -7
  137. package/dist/hitl/livePendingAsk.d.ts +3 -3
  138. package/dist/hitl/livePendingAsk.js +7 -18
  139. package/dist/hitl/parkResolver.d.ts +2 -24
  140. package/dist/hitl/parkResolver.js +61 -97
  141. package/dist/hitl/persistedRulesWire.d.ts +24 -0
  142. package/dist/hitl/persistedRulesWire.js +122 -2
  143. package/dist/hitl/planReviewWire.d.ts +26 -13
  144. package/dist/hitl/planReviewWire.js +112 -78
  145. package/dist/hitl/refusedToolNameProse.d.ts +0 -1
  146. package/dist/hitl/refusedToolNameProse.js +0 -3
  147. package/dist/hitl/replayedApproval.d.ts +4 -3
  148. package/dist/hitl/replayedApproval.js +7 -4
  149. package/dist/hitl/sessionPolicyDeliverable.js +2 -4
  150. package/dist/hitl/sessionPolicyWire.d.ts +32 -20
  151. package/dist/hitl/sessionPolicyWire.js +162 -52
  152. package/dist/hitl/standingRows.d.ts +20 -2
  153. package/dist/hitl/standingRows.js +69 -8
  154. package/dist/hitl/toolApprovalWire.d.ts +87 -152
  155. package/dist/hitl/toolApprovalWire.js +591 -380
  156. package/dist/hookMatcherVerdict.d.ts +6 -1
  157. package/dist/hookMatcherVerdict.js +14 -7
  158. package/dist/hooksWireCaps.d.ts +2 -2
  159. package/dist/hooksWireCaps.js +59 -55
  160. package/dist/i18n/messages.en.d.ts +121 -0
  161. package/dist/i18n/messages.en.js +119 -0
  162. package/dist/i18n/messages.zh.d.ts +3 -0
  163. package/dist/i18n/messages.zh.js +120 -0
  164. package/dist/i18n/translate.d.ts +25 -0
  165. package/dist/i18n/translate.js +127 -0
  166. package/dist/index.d.ts +53 -18
  167. package/dist/index.js +38 -10
  168. package/dist/inheritEnvCapability.d.ts +31 -0
  169. package/dist/inheritEnvCapability.js +104 -0
  170. package/dist/liveModelCatalog.d.ts +1 -2
  171. package/dist/liveModelCatalog.js +2 -6
  172. package/dist/liveQuestionStore.d.ts +2 -21
  173. package/dist/mcpLiveness.d.ts +2 -1
  174. package/dist/mcpProbeWire.d.ts +6 -1
  175. package/dist/mcpProbeWire.js +1 -1
  176. package/dist/mcpWireCaps.d.ts +13 -2
  177. package/dist/mcpWireCaps.js +48 -0
  178. package/dist/memoryEntriesWire.d.ts +4 -9
  179. package/dist/model/modelSupplyRules.d.ts +0 -2
  180. package/dist/model/modelSupplyRules.js +3 -12
  181. package/dist/model/modelsPolicy.d.ts +0 -5
  182. package/dist/model/modelsPolicy.js +6 -36
  183. package/dist/model/subagentModelWord.d.ts +31 -0
  184. package/dist/model/subagentModelWord.js +261 -0
  185. package/dist/notifications.d.ts +6 -0
  186. package/dist/notifications.js +71 -23
  187. package/dist/outputStyleSeatCapability.d.ts +0 -3
  188. package/dist/outputStyleSeatCapability.js +0 -3
  189. package/dist/ownKey.d.ts +15 -0
  190. package/dist/ownKey.js +60 -3
  191. package/dist/panelReduce.d.ts +15 -9
  192. package/dist/panelReduce.js +680 -549
  193. package/dist/panelStateHolder.d.ts +3 -7
  194. package/dist/panelStateHolder.js +14 -130
  195. package/dist/peerLaneCapability.d.ts +0 -4
  196. package/dist/peerLaneCapability.js +0 -6
  197. package/dist/permissionRulesWriteCapability.d.ts +0 -4
  198. package/dist/permissionRulesWriteCapability.js +0 -6
  199. package/dist/permissionWireCaps.d.ts +2 -2
  200. package/dist/permissionWireCaps.js +2 -0
  201. package/dist/permissionsAllowGrantCapability.d.ts +0 -4
  202. package/dist/permissionsAllowGrantCapability.js +0 -6
  203. package/dist/permissionsDeclaration.d.ts +0 -11
  204. package/dist/permissionsDeclaration.js +60 -53
  205. package/dist/pluginHooksWire.d.ts +1 -1
  206. package/dist/pluginHooksWire.js +3 -6
  207. package/dist/preemptWire.d.ts +44 -0
  208. package/dist/preemptWire.js +83 -0
  209. package/dist/printToolResultFrame.js +15 -4
  210. package/dist/replayBody.d.ts +3 -0
  211. package/dist/replayBody.js +14 -0
  212. package/dist/request/taskRequest.d.ts +0 -1
  213. package/dist/request/taskRequest.js +0 -3
  214. package/dist/resumeRefusalCopy.d.ts +2 -1
  215. package/dist/resumeRefusalCopy.js +38 -2
  216. package/dist/retryStatus.d.ts +8 -0
  217. package/dist/retryStatus.js +106 -1
  218. package/dist/rewindArchiveCapability.d.ts +0 -4
  219. package/dist/rewindArchiveCapability.js +2 -10
  220. package/dist/rewindArchiveReading.d.ts +0 -1
  221. package/dist/rewindArchiveReading.js +0 -3
  222. package/dist/runCancelContext.d.ts +2 -1
  223. package/dist/runCancelContext.js +4 -2
  224. package/dist/runReattachPolicy.d.ts +31 -0
  225. package/dist/runReattachPolicy.js +46 -0
  226. package/dist/runTerminal.d.ts +3 -6
  227. package/dist/runTerminal.js +8 -9
  228. package/dist/sandboxWire.d.ts +3 -1
  229. package/dist/sandboxWire.js +76 -27
  230. package/dist/scenarioWire.js +1 -1
  231. package/dist/seam.d.ts +24 -2
  232. package/dist/seam.js +15 -3
  233. package/dist/seatContract.d.ts +53 -10
  234. package/dist/seatContract.js +132 -81
  235. package/dist/sessionPolicyCapability.d.ts +0 -4
  236. package/dist/sessionPolicyCapability.js +0 -6
  237. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
  238. package/dist/sessionSyncFileHistoryCapability.js +0 -3
  239. package/dist/skillToolListsCapability.d.ts +0 -3
  240. package/dist/skillToolListsCapability.js +0 -3
  241. package/dist/sqlEngineCapability.d.ts +0 -4
  242. package/dist/sqlEngineCapability.js +0 -6
  243. package/dist/steerPriorityCapability.d.ts +0 -3
  244. package/dist/steerPriorityCapability.js +0 -3
  245. package/dist/streamDrainingLegs.d.ts +4 -0
  246. package/dist/streamDrainingLegs.js +6 -1
  247. package/dist/subagent/engineCompactWire.d.ts +0 -1
  248. package/dist/subagent/engineCompactWire.js +7 -5
  249. package/dist/subagent/engineTaskHandleWire.js +4 -7
  250. package/dist/subagentContentStore.js +1 -11
  251. package/dist/submitReopen.d.ts +24 -0
  252. package/dist/submitReopen.js +75 -0
  253. package/dist/terminalStatuses.d.ts +3 -0
  254. package/dist/terminalStatuses.js +10 -2
  255. package/dist/toolResult.d.ts +10 -1
  256. package/dist/toolResult.js +34 -6
  257. package/dist/toolRoster.d.ts +0 -2
  258. package/dist/toolRoster.js +0 -2
  259. package/dist/turnFailurePresentation.d.ts +28 -0
  260. package/dist/turnFailurePresentation.js +205 -0
  261. package/dist/userInvokedSkillsCapability.d.ts +0 -3
  262. package/dist/userInvokedSkillsCapability.js +0 -3
  263. package/dist/webSearchBackendCapability.d.ts +0 -4
  264. package/dist/webSearchBackendCapability.js +0 -6
  265. package/dist/wireErrorTriage.js +5 -24
  266. package/dist/wireFailureShape.d.ts +62 -5
  267. package/dist/wireFailureShape.js +105 -5
  268. package/dist/wireRefusalCopy.d.ts +12 -2
  269. package/dist/wireRefusalCopy.js +50 -52
  270. package/dist/workflowsJournalCapability.d.ts +0 -4
  271. package/dist/workflowsJournalCapability.js +0 -6
  272. package/dist/writeProtectionCapability.d.ts +0 -4
  273. package/dist/writeProtectionCapability.js +0 -6
  274. package/docs/INTEGRATION-CLIENTS.md +1305 -46
  275. package/package.json +5 -4
  276. package/dist/attachmentSeatCapability.d.ts +0 -12
  277. package/dist/attachmentSeatCapability.js +0 -23
  278. package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
  279. package/dist/hitl/approvalOutcomeNote.js +0 -29
  280. package/dist/sessionReadRedactionCapability.d.ts +0 -13
  281. package/dist/sessionReadRedactionCapability.js +0 -35
@@ -134,24 +134,21 @@ export const ABSENT_SETTLE_MS = 30_000;
134
134
  const SETTLED_RETENTION_MS = ABSENT_SETTLE_MS * 4;
135
135
  export const MAX_HELD_WIRE_TICK_BEATS = 16;
136
136
  const MAX_HELD_WIRE_TICKS = 64;
137
- const MAX_ALIAS_PER_KIND = 2048;
138
- const MAX_WIRE_KEYS = 8192;
139
- const MAX_OWNED_TAILS = 8192;
140
- const MAX_RUNNING = 4096;
141
- const MAX_ENDED = 4096;
142
- const MAX_HELD_ROWS = 4096;
143
- const MAX_ROWS = 8192;
137
+ const MAX_RECORDS = 8192;
138
+ const MAX_IDS_PER_RECORD = 16;
139
+ const MAX_CARD_HINTS = 2048;
144
140
  export const PANEL_DELTA_OPS = Object.freeze(['upsert', 'usage_delta', 'terminal', 'remove']);
145
- export const PANEL_REDUCE_STATE_KEYS = Object.freeze(['__panelReduceState', 'records', 'alias', 'pending', 'sessions', 'overflowed', 'counts']);
141
+ export const PANEL_REDUCE_STATE_KEYS = Object.freeze(['__panelReduceState', 'records', 'index', 'cards', 'pending', 'sessions', 'overflowed', 'counts']);
146
142
  export function createPanelReduceState() {
147
143
  const s = {
148
144
  __panelReduceState: true,
149
145
  records: PMap.empty(),
150
- alias: PMap.empty(),
146
+ index: PMap.empty(),
147
+ cards: PMap.empty(),
151
148
  pending: PMap.empty(),
152
149
  sessions: PMap.empty(),
153
150
  overflowed: false,
154
- counts: { alias: { t: 0, p: 0, w: 0 }, wire: 0, owned: 0, running: 0, ended: 0, held: 0, rows: 0 },
151
+ counts: { nextRecord: 0, nextAnnounce: 0, unattributedTicks: 0, endedRows: 0 },
155
152
  };
156
153
  return Object.freeze(s);
157
154
  }
@@ -160,7 +157,8 @@ function impl(s) {
160
157
  }
161
158
  class Step {
162
159
  records;
163
- alias;
160
+ index;
161
+ cards;
164
162
  pending;
165
163
  sessionsDraft;
166
164
  overflowed;
@@ -169,28 +167,35 @@ class Step {
169
167
  facts = [];
170
168
  constructor(s) {
171
169
  this.records = s.records.draft();
172
- this.alias = s.alias.draft();
170
+ this.index = s.index.draft();
171
+ this.cards = s.cards.draft();
173
172
  this.pending = s.pending.draft();
174
173
  this.sessionsDraft = s.sessions.draft();
175
174
  this.overflowed = s.overflowed;
176
- this.counts = { alias: { ...s.counts.alias }, wire: s.counts.wire, owned: s.counts.owned, running: s.counts.running, ended: s.counts.ended, held: s.counts.held, rows: s.counts.rows };
175
+ this.counts = { nextRecord: s.counts.nextRecord, nextAnnounce: s.counts.nextAnnounce, unattributedTicks: s.counts.unattributedTicks, endedRows: s.counts.endedRows };
177
176
  }
178
177
  freeze() {
179
178
  return Object.freeze({
180
179
  __panelReduceState: true,
181
180
  records: this.records.freeze(),
182
- alias: this.alias.freeze(),
181
+ index: this.index.freeze(),
182
+ cards: this.cards.freeze(),
183
183
  pending: this.pending.freeze(),
184
184
  sessions: this.sessionsDraft.freeze(),
185
185
  overflowed: this.overflowed,
186
- counts: Object.freeze({ ...this.counts, alias: Object.freeze({ ...this.counts.alias }) }),
186
+ counts: Object.freeze({ ...this.counts }),
187
187
  });
188
188
  }
189
- rec(key) {
190
- return this.records.get(key);
189
+ rec(rid) {
190
+ return this.records.get(rid);
191
191
  }
192
- put(key, patch) {
193
- const old = this.records.get(key) ?? {};
192
+ find(id) {
193
+ return this.index.get(id);
194
+ }
195
+ put(rid, patch) {
196
+ const old = this.records.get(rid);
197
+ if (old === undefined)
198
+ return;
194
199
  const next = { ...old };
195
200
  for (const [f, v] of Object.entries(patch)) {
196
201
  if (v === undefined)
@@ -199,70 +204,29 @@ class Step {
199
204
  next[f] = v;
200
205
  }
201
206
  const n = next;
202
- this.counts.wire += (n.wire !== undefined ? 1 : 0) - (old.wire !== undefined ? 1 : 0);
203
- this.counts.owned += (n.ownedBy !== undefined ? 1 : 0) - (old.ownedBy !== undefined ? 1 : 0);
204
- this.counts.running += (n.running !== undefined ? 1 : 0) - (old.running !== undefined ? 1 : 0);
205
- this.counts.ended += (n.ended !== undefined ? 1 : 0) - (old.ended !== undefined ? 1 : 0);
206
- this.counts.held += (n.held !== undefined ? 1 : 0) - (old.held !== undefined ? 1 : 0);
207
- this.counts.rows += (n.row !== undefined ? 1 : 0) - (old.row !== undefined ? 1 : 0);
208
- if (Object.keys(next).length === 0)
209
- this.records.delete(key);
210
- else
211
- this.records.set(key, n);
212
- const from = old.ownedBy?.wireId;
213
- const to = n.ownedBy?.wireId;
214
- if (from !== to) {
215
- if (from !== undefined)
216
- this.linkOwned(from, key, false);
217
- if (to !== undefined)
218
- this.linkOwned(to, key, true);
219
- }
207
+ this.counts.endedRows += (rowEnded(n) ? 1 : 0) - (rowEnded(old) ? 1 : 0);
208
+ this.records.set(rid, n);
220
209
  }
221
- linkOwned(owner, tail, add) {
222
- const r = this.records.get(owner) ?? {};
223
- const cur = r.owns ?? [];
224
- if (cur.includes(tail) === add)
210
+ drop(rid) {
211
+ const old = this.records.get(rid);
212
+ if (old === undefined)
225
213
  return;
226
- const owns = add ? [...cur, tail] : cur.filter((t) => t !== tail);
227
- const next = { ...r };
228
- if (owns.length > 0)
229
- next.owns = owns;
230
- else
231
- delete next.owns;
232
- if (Object.keys(next).length === 0)
233
- this.records.delete(owner);
234
- else
235
- this.records.set(owner, next);
236
- }
237
- ownedTails(owner) {
238
- return this.records.get(owner)?.owns ?? [];
239
- }
240
- aliasGet(kind, key, touch) {
241
- const k = `${kind}:${key}`;
242
- const e = this.alias.get(k);
243
- if (e !== undefined && touch)
244
- this.alias.touch(k);
245
- return e;
246
- }
247
- aliasHas(kind, key) {
248
- return this.alias.has(`${kind}:${key}`);
249
- }
250
- aliasSet(kind, key, entry) {
251
- const k = `${kind}:${key}`;
252
- const had = this.alias.has(k);
253
- if (had)
254
- this.alias.delete(k);
255
- else
256
- this.counts.alias[kind]++;
257
- this.alias.set(k, entry);
258
- if (this.counts.alias[kind] > MAX_ALIAS_PER_KIND) {
259
- const prefix = `${kind}:`;
260
- const oldest = this.alias.first((key2) => key2.startsWith(prefix));
261
- if (oldest !== undefined) {
262
- this.alias.delete(oldest);
263
- this.counts.alias[kind]--;
264
- }
265
- }
214
+ if (rowEnded(old))
215
+ this.counts.endedRows--;
216
+ this.records.delete(rid);
217
+ }
218
+ create(init) {
219
+ const rid = `r${this.counts.nextRecord}`;
220
+ this.counts.nextRecord++;
221
+ this.records.set(rid, {
222
+ ...(init.tail !== undefined ? { tail: init.tail } : {}),
223
+ ...(init.id !== undefined ? { ids: [{ id: init.id }] } : {}),
224
+ });
225
+ if (init.tail !== undefined)
226
+ this.index.set(init.tail, rid);
227
+ if (init.id !== undefined)
228
+ this.index.set(init.id, rid);
229
+ return rid;
266
230
  }
267
231
  session(sessionKey) {
268
232
  return (this.sessionsDraft.get(sessionKey) ?? PMap.empty()).draft();
@@ -282,41 +246,263 @@ class Step {
282
246
  this.sessionsDraft.delete(k);
283
247
  }
284
248
  }
285
- function boundFields(d) {
286
- if (d.counts.wire > MAX_WIRE_KEYS) {
287
- const k = d.records.first((_, r) => r.wire?.retired === true) ?? d.records.first((_, r) => r.wire !== undefined);
288
- if (k !== undefined)
289
- d.put(k, { wire: undefined });
249
+ function rowEnded(r) {
250
+ return r.row?.phase === 'ended';
251
+ }
252
+ function idsOf(r) {
253
+ const out = [];
254
+ if (r.tail !== undefined)
255
+ out.push(r.tail);
256
+ for (const b of r.ids ?? [])
257
+ if (!out.includes(b.id))
258
+ out.push(b.id);
259
+ if (r.consumerKey !== undefined && !out.includes(r.consumerKey))
260
+ out.push(r.consumerKey);
261
+ return out;
262
+ }
263
+ function keyOf(r) {
264
+ return r.consumerKey ?? r.tail ?? r.ids?.[0]?.id ?? '';
265
+ }
266
+ function bindingOf(r, id) {
267
+ return (r.ids ?? []).find((b) => b.id === id);
268
+ }
269
+ function hasCycleSeq(c) {
270
+ return c?.cycleSeq !== undefined;
271
+ }
272
+ function formerGeneration(r, id) {
273
+ const b = bindingOf(r, id);
274
+ if (b === undefined)
275
+ return false;
276
+ if (b.superseded === true)
277
+ return true;
278
+ return b.gen !== undefined && cycleOrder(b.gen, r.cycle) === 'before';
279
+ }
280
+ function frameCycleOn(r, id, own) {
281
+ return mergeCycle(cycleOf(own), r !== undefined ? bindingOf(r, id)?.gen : undefined);
282
+ }
283
+ function newerCycle(a, b) {
284
+ if (a === undefined)
285
+ return b;
286
+ if (b === undefined)
287
+ return a;
288
+ return cycleOrder(a, b) === 'before' ? b : a;
289
+ }
290
+ function recordOrdinal(rid) {
291
+ return Number(rid.slice(1));
292
+ }
293
+ function addId(d, rid, id, gen) {
294
+ const r = d.rec(rid);
295
+ if (r === undefined)
296
+ return;
297
+ const ids = [...(r.ids ?? [])];
298
+ const g = gen !== undefined && !cycleEmpty(gen) ? cycleOf(gen) : undefined;
299
+ const at = ids.findIndex((b) => b.id === id);
300
+ const cur = at >= 0 ? ids[at] : undefined;
301
+ if (cur !== undefined) {
302
+ if (g !== undefined && (cur.gen === undefined || cycleOrder(cur.gen, g) === 'before')) {
303
+ ids[at] = { ...cur, gen: g };
304
+ d.put(rid, { ids });
305
+ }
306
+ d.index.set(id, rid);
307
+ return;
290
308
  }
291
- if (d.counts.owned > MAX_OWNED_TAILS) {
292
- const k = d.records.first((_, r) => r.ownedBy?.retired === true) ?? d.records.first((_, r) => r.ownedBy !== undefined);
293
- if (k !== undefined)
294
- d.put(k, { ownedBy: undefined });
309
+ ids.push({ id, ...(g !== undefined ? { gen: g } : {}) });
310
+ while (ids.length > MAX_IDS_PER_RECORD) {
311
+ const k = ids.findIndex((b) => b.id !== r.currentRun && b.id !== r.consumerKey && b.id !== id);
312
+ if (k < 0)
313
+ break;
314
+ const [gone] = ids.splice(k, 1);
315
+ if (gone !== undefined && d.index.get(gone.id) === rid)
316
+ d.index.delete(gone.id);
317
+ }
318
+ d.put(rid, { ids });
319
+ d.index.set(id, rid);
320
+ }
321
+ function bind(d, first, kind, second, gen) {
322
+ const two = second !== undefined && second.length > 0 && second !== first ? second : undefined;
323
+ const a = d.find(first);
324
+ const b = two !== undefined ? d.find(two) : undefined;
325
+ if (a === undefined && b === undefined) {
326
+ const rid = d.create({ tail: first });
327
+ if (two !== undefined)
328
+ addId(d, rid, two, gen);
329
+ return rid;
330
+ }
331
+ if (a === undefined) {
332
+ const rb = b !== undefined ? d.rec(b) : undefined;
333
+ if (b === undefined || rb === undefined || (rb.tail !== undefined && rb.tail !== first))
334
+ return d.create({ tail: first });
335
+ if (rb.tail === undefined) {
336
+ d.put(b, { tail: first });
337
+ d.index.set(first, b);
338
+ }
339
+ if (two !== undefined)
340
+ addId(d, b, two, gen);
341
+ return b;
342
+ }
343
+ if (kind === 'tail' && d.rec(a)?.tail === undefined)
344
+ d.put(a, { tail: first });
345
+ if (b === undefined || b === a) {
346
+ if (two !== undefined)
347
+ addId(d, a, two, gen);
348
+ return a;
349
+ }
350
+ const ra = d.rec(a);
351
+ const rb = d.rec(b);
352
+ if (ra?.tail !== undefined && rb?.tail !== undefined && ra.tail !== rb.tail)
353
+ return a;
354
+ const s = merge(d, a, b);
355
+ if (two !== undefined)
356
+ addId(d, s, two, gen);
357
+ return s;
358
+ }
359
+ function merge(d, a, b) {
360
+ const ra = d.rec(a);
361
+ const rb = d.rec(b);
362
+ if (ra === undefined || rb === undefined)
363
+ return ra === undefined ? b : a;
364
+ const aFirst = ra.announceSeq !== undefined
365
+ ? rb.announceSeq === undefined || ra.announceSeq < rb.announceSeq
366
+ : rb.announceSeq === undefined && recordOrdinal(a) < recordOrdinal(b);
367
+ const s = aFirst ? a : b;
368
+ const l = aFirst ? b : a;
369
+ const rs = aFirst ? ra : rb;
370
+ const rl = aFirst ? rb : ra;
371
+ const ids = [...(rs.ids ?? [])];
372
+ for (const x of rl.ids ?? []) {
373
+ const at = ids.findIndex((y) => y.id === x.id);
374
+ const y = at >= 0 ? ids[at] : undefined;
375
+ if (y === undefined)
376
+ ids.push(x);
377
+ else if (x.gen !== undefined && (y.gen === undefined || cycleOrder(y.gen, x.gen) === 'before'))
378
+ ids[at] = { ...y, gen: x.gen };
379
+ }
380
+ if (rl.tail !== undefined && rs.tail !== undefined && rl.tail !== rs.tail && !ids.some((y) => y.id === rl.tail))
381
+ ids.push({ id: rl.tail });
382
+ const order = cycleOrder(genOf(rs), genOf(rl));
383
+ const loserNewer = order === 'before';
384
+ const cycle = newerCycle(newerCycle(rs.cycle, rl.cycle), loserNewer ? rl.row?.endCycle : undefined);
385
+ const loserUsage = !hasCycleSeq(cycle) || rl.cycle !== undefined;
386
+ const merged = loserNewer ? adoptRow(rs.row, rl.row) : order === 'after' ? { row: rs.row, filled: {}, usage: undefined, endedNow: false, revived: false } : mergeRows(rs.row, rl.row, cycle, loserUsage);
387
+ d.put(s, {
388
+ tail: rs.tail ?? rl.tail,
389
+ ids,
390
+ cycle,
391
+ ended: newerCycle(rs.ended, rl.ended),
392
+ currentRun: loserNewer ? (rl.currentRun ?? rs.currentRun) : (rs.currentRun ?? rl.currentRun),
393
+ running: rs.running ?? rl.running,
394
+ held: rs.held ?? rl.held,
395
+ resident: rs.resident ?? rl.resident,
396
+ anchor: rs.anchor ?? rl.anchor,
397
+ row: merged.row,
398
+ });
399
+ for (const id of idsOf(rl))
400
+ d.index.set(id, s);
401
+ d.drop(l);
402
+ const after = d.rec(s);
403
+ if (after === undefined)
404
+ return s;
405
+ const key = keyOf(after);
406
+ if (rl.row?.announced === true)
407
+ d.deltas.push({ op: 'remove', canonicalId: keyOf(rl), supersededBy: key });
408
+ if (rs.row?.announced === true && merged.row !== undefined) {
409
+ if (merged.revived) {
410
+ d.deltas.push({ op: 'upsert', canonicalId: key, revived: true, fields: { ...merged.row.fields } });
411
+ const u = fullUsage(key, merged.row);
412
+ if (u !== undefined)
413
+ d.deltas.push(u);
414
+ if (merged.row.phase === 'ended')
415
+ mintTerminal(d, key, merged.row.isError === true, merged.row.report, merged.row.cause ?? 'end');
416
+ }
417
+ else {
418
+ if (Object.keys(merged.filled).length > 0)
419
+ d.deltas.push({ op: 'upsert', canonicalId: key, fields: merged.filled });
420
+ if (merged.usage !== undefined)
421
+ d.deltas.push(usageDelta(key, merged.usage));
422
+ if (merged.endedNow)
423
+ mintTerminal(d, key, merged.row.isError === true, merged.row.report, 'end');
424
+ }
295
425
  }
296
- if (d.counts.running > MAX_RUNNING) {
297
- d.overflowed = true;
298
- const k = d.records.first((_, r) => r.running === true);
299
- if (k !== undefined)
300
- d.put(k, { running: undefined });
426
+ return s;
427
+ }
428
+ function genOf(r) {
429
+ return newerCycle(r.cycle, r.row?.endCycle);
430
+ }
431
+ function adoptRow(s, l) {
432
+ if (l === undefined)
433
+ return { row: s, filled: {}, usage: undefined, endedNow: false, revived: false };
434
+ if (s === undefined)
435
+ return { row: l, filled: {}, usage: undefined, endedNow: false, revived: false };
436
+ const fields = { ...s.fields, ...l.fields };
437
+ delete fields.absence;
438
+ return { row: { ...l, announced: s.announced, fields }, filled: {}, usage: undefined, endedNow: false, revived: s.announced };
439
+ }
440
+ function mergeRows(s, l, cycle, loserUsage) {
441
+ if (l === undefined)
442
+ return { row: s, filled: {}, usage: undefined, endedNow: false, revived: false };
443
+ if (s === undefined)
444
+ return { row: l, filled: {}, usage: undefined, endedNow: false, revived: false };
445
+ const filled = changedFields(s.fields, l.fields, Object.keys(l.fields));
446
+ delete filled.absence;
447
+ const carrier = loserUsage ? { totalTokens: l.totalTokens, toolUses: l.toolUses, final: l.final } : {};
448
+ const u = foldUsage({
449
+ ...s,
450
+ ...(l.gateBound === true ? { gateBound: true } : {}),
451
+ ...(s.deferredEndError === undefined && l.deferredEndError !== undefined ? { deferredEndError: l.deferredEndError } : {}),
452
+ tickSeen: s.tickSeen || l.tickSeen,
453
+ fields: { ...s.fields, ...filled },
454
+ }, carrier);
455
+ let row = u.row;
456
+ const lateEnd = l.endCycle !== undefined && cycleOrder(l.endCycle, cycle) === 'before';
457
+ const endedNow = row.phase === 'running' && l.phase === 'ended' && !lateEnd;
458
+ if (endedNow) {
459
+ const f = { ...row.fields };
460
+ delete f.absence;
461
+ row = {
462
+ ...row,
463
+ phase: 'ended',
464
+ fields: f,
465
+ ...(l.isError !== undefined ? { isError: l.isError } : {}),
466
+ ...(l.report !== undefined ? { report: l.report } : {}),
467
+ ...(l.cause !== undefined ? { cause: l.cause } : {}),
468
+ ...(l.endCycle !== undefined ? { endCycle: l.endCycle } : {}),
469
+ };
301
470
  }
302
- if (d.counts.ended > MAX_ENDED) {
303
- const k = d.records.first((_, r) => r.ended !== undefined);
304
- if (k !== undefined)
305
- d.put(k, { ended: undefined });
471
+ return { row, filled, usage: u.change, endedNow, revived: false };
472
+ }
473
+ function noteCard(d, card) {
474
+ if (card === undefined || card.length === 0)
475
+ return;
476
+ if (d.cards.has(card)) {
477
+ d.cards.touch(card);
478
+ return;
306
479
  }
307
- if (d.counts.held > MAX_HELD_ROWS) {
308
- const k = d.records.first((_, r) => r.held !== undefined);
309
- if (k !== undefined)
310
- d.put(k, { held: undefined });
480
+ d.cards.set(card, true);
481
+ if (d.cards.size > MAX_CARD_HINTS) {
482
+ const oldest = d.cards.first(() => true);
483
+ if (oldest !== undefined)
484
+ d.cards.delete(oldest);
311
485
  }
312
- if (d.counts.rows > MAX_ROWS) {
313
- const k = d.records.first((_, r) => r.row?.phase === 'ended') ?? d.records.first((_, r) => r.row !== undefined);
314
- if (k !== undefined) {
315
- const announced = d.rec(k)?.row?.announced === true;
316
- d.put(k, { row: undefined });
317
- if (announced)
318
- d.deltas.push({ op: 'remove', canonicalId: k });
319
- }
486
+ }
487
+ function evict(d, rid) {
488
+ const r = d.rec(rid);
489
+ if (r === undefined)
490
+ return;
491
+ if (r.running === true && !rowEnded(r))
492
+ d.overflowed = true;
493
+ for (const id of idsOf(r))
494
+ if (d.index.get(id) === rid)
495
+ d.index.delete(id);
496
+ d.drop(rid);
497
+ if (r.row?.announced === true)
498
+ d.deltas.push({ op: 'remove', canonicalId: keyOf(r) });
499
+ }
500
+ function boundRecords(d) {
501
+ while (d.records.size > MAX_RECORDS) {
502
+ const victim = (d.counts.endedRows > 0 ? d.records.first((_, r) => rowEnded(r)) : undefined) ?? d.records.first(() => true);
503
+ if (victim === undefined)
504
+ return;
505
+ evict(d, victim);
320
506
  }
321
507
  }
322
508
  export function panelEndFact(taskId, isError, extra) {
@@ -335,6 +521,67 @@ function terminalDelta(key, isError, report, cause) {
335
521
  function mintTerminal(d, key, isError, report, cause) {
336
522
  d.deltas.push(terminalDelta(key, isError, report, cause));
337
523
  }
524
+ function withCount(row, k, v) {
525
+ return k === 'totalTokens' ? { ...row, totalTokens: v } : { ...row, toolUses: v };
526
+ }
527
+ function foldUsage(row, c) {
528
+ let next = row;
529
+ const final = { ...(row.final ?? {}) };
530
+ const vals = {};
531
+ let finalChanged = false;
532
+ for (const k of ['totalTokens', 'toolUses']) {
533
+ const v = c[k];
534
+ if (v === undefined)
535
+ continue;
536
+ const isFinal = c.final?.[k] === true;
537
+ const cur = next[k];
538
+ const curFinal = final[k] === true;
539
+ if (curFinal && !isFinal)
540
+ continue;
541
+ if (cur === undefined || v > cur) {
542
+ vals[k] = v;
543
+ next = withCount(next, k, v);
544
+ if (isFinal && !curFinal) {
545
+ final[k] = true;
546
+ finalChanged = true;
547
+ }
548
+ }
549
+ else if (v === cur && isFinal && !curFinal) {
550
+ final[k] = true;
551
+ finalChanged = true;
552
+ }
553
+ }
554
+ if (finalChanged)
555
+ next = { ...next, final };
556
+ if (vals.totalTokens === undefined && vals.toolUses === undefined && !finalChanged)
557
+ return { row: next, change: undefined };
558
+ return { row: next, change: { ...vals, ...(finalChanged ? { final } : {}) } };
559
+ }
560
+ function usageDelta(key, u) {
561
+ return {
562
+ op: 'usage_delta',
563
+ canonicalId: key,
564
+ ...(u.totalTokens !== undefined ? { totalTokens: u.totalTokens } : {}),
565
+ ...(u.toolUses !== undefined ? { toolUses: u.toolUses } : {}),
566
+ ...(u.final !== undefined ? { final: u.final } : {}),
567
+ };
568
+ }
569
+ function fullUsage(key, row) {
570
+ const fin = row.final !== undefined && (row.final.totalTokens === true || row.final.toolUses === true) ? row.final : undefined;
571
+ if (row.totalTokens === undefined && row.toolUses === undefined && fin === undefined)
572
+ return undefined;
573
+ return usageDelta(key, { ...(row.totalTokens !== undefined ? { totalTokens: row.totalTokens } : {}), ...(row.toolUses !== undefined ? { toolUses: row.toolUses } : {}), ...(fin !== undefined ? { final: fin } : {}) });
574
+ }
575
+ function fleetCarrier(ev) {
576
+ const f = ev.final;
577
+ const final = { ...(f?.totalTokens === true ? { totalTokens: true } : {}), ...(f?.toolUses === true ? { toolUses: true } : {}) };
578
+ return { totalTokens: ev.totalTokens, toolUses: ev.toolUses, final };
579
+ }
580
+ function finalityOf(tokens, toolUses) {
581
+ if (tokens === undefined && toolUses === undefined)
582
+ return undefined;
583
+ return { ...(tokens !== undefined ? { totalTokens: true } : {}), ...(toolUses !== undefined ? { toolUses: true } : {}) };
584
+ }
338
585
  function tickFields(ev) {
339
586
  return {
340
587
  ...(ev.name !== undefined ? { name: ev.name } : {}),
@@ -372,88 +619,95 @@ function changedFields(row, next, onlyMissing) {
372
619
  return out;
373
620
  }
374
621
  const TICK_LATE_BIND = Object.freeze(['prompt', 'description', 'name']);
375
- function usageDelta(key, row, tokens, toolUses) {
376
- const t = tokens !== undefined && tokens !== row?.totalTokens ? tokens : undefined;
377
- const u = toolUses !== undefined && toolUses !== row?.toolUses ? toolUses : undefined;
378
- if (t === undefined && u === undefined)
379
- return undefined;
380
- return { op: 'usage_delta', canonicalId: key, ...(t !== undefined ? { totalTokens: t } : {}), ...(u !== undefined ? { toolUses: u } : {}) };
381
- }
382
- function announce(d, key, row) {
622
+ function announce(d, rid) {
623
+ const r = d.rec(rid);
624
+ const row = r?.row;
625
+ if (r === undefined || row === undefined || row.announced)
626
+ return;
627
+ const key = keyOf(r);
628
+ d.put(rid, { consumerKey: key, announceSeq: d.counts.nextAnnounce, row: { ...row, announced: true } });
629
+ d.counts.nextAnnounce++;
383
630
  d.deltas.push({ op: 'upsert', canonicalId: key, created: true, fields: { ...row.fields } });
384
- const u = usageDelta(key, undefined, row.totalTokens, row.toolUses);
631
+ const u = fullUsage(key, row);
385
632
  if (u !== undefined)
386
633
  d.deltas.push(u);
387
634
  if (row.phase === 'ended')
388
635
  mintTerminal(d, key, row.isError === true, row.report, 'end');
389
- return { ...row, announced: true };
390
636
  }
391
- function foldTick(d, ev) {
392
- const key = ev.taskId;
393
- const row = d.rec(key)?.row;
637
+ function foldTick(d, rid, ev, cardBound) {
638
+ const r = d.rec(rid);
639
+ if (r === undefined)
640
+ return;
641
+ const row = r.row;
642
+ const gate = cardBound ? { gateBound: true } : {};
643
+ const wireId = ev.wireTaskId ?? ev.taskId;
644
+ const attributable = !hasCycleSeq(r.cycle) && (r.currentRun === undefined || r.currentRun === wireId);
645
+ if (!attributable)
646
+ d.counts.unattributedTicks++;
647
+ const carrier = attributable ? { totalTokens: ev.totalTokens, toolUses: ev.toolUses } : {};
394
648
  if (row === undefined || !row.announced) {
395
- const fresh = row !== undefined
396
- ? { ...row, lane: 'tick', fields: { ...row.fields, ...tickFields(ev) }, totalTokens: ev.totalTokens, toolUses: ev.toolUses }
397
- : { phase: 'running', lane: 'tick', announced: false, fields: tickFields(ev), totalTokens: ev.totalTokens, toolUses: ev.toolUses };
398
- d.put(key, { row: announce(d, key, fresh) });
649
+ const base = row !== undefined
650
+ ? { ...row, ...gate, tickSeen: true, fields: { ...row.fields, ...tickFields(ev) } }
651
+ : { phase: 'running', ...gate, tickSeen: true, announced: false, fields: tickFields(ev) };
652
+ d.put(rid, { row: foldUsage(base, carrier).row });
653
+ announce(d, rid);
399
654
  return;
400
655
  }
401
- if (row.phase !== 'running')
656
+ const key = keyOf(r);
657
+ if (row.phase !== 'running') {
658
+ const u = foldUsage(row, carrier);
659
+ if (u.change !== undefined)
660
+ d.deltas.push(usageDelta(key, u.change));
661
+ d.put(rid, { row: u.row });
402
662
  return;
403
- const next = tickFields(ev);
404
- const changed = changedFields(row.fields, next, TICK_LATE_BIND);
663
+ }
664
+ const changed = changedFields(row.fields, tickFields(ev), TICK_LATE_BIND);
405
665
  if (row.fields.absence)
406
666
  changed.absence = null;
407
667
  if (Object.keys(changed).length > 0)
408
668
  d.deltas.push({ op: 'upsert', canonicalId: key, fields: changed });
409
- const u = usageDelta(key, row, ev.totalTokens, ev.toolUses);
410
- if (u !== undefined)
411
- d.deltas.push(u);
669
+ const u = foldUsage(row, carrier);
670
+ if (u.change !== undefined)
671
+ d.deltas.push(usageDelta(key, u.change));
412
672
  const fields = { ...row.fields, ...changed };
413
673
  if (changed.absence === null)
414
674
  delete fields.absence;
415
- d.put(key, { row: { ...row, lane: 'tick', fields, totalTokens: ev.totalTokens, toolUses: ev.toolUses } });
675
+ d.put(rid, { row: { ...u.row, ...gate, tickSeen: true, fields } });
416
676
  }
417
- function foldFleetRow(d, ev, prior) {
418
- const key = ev.taskId;
419
- const row = d.rec(key)?.row;
420
- const order = cycleOrder(prior, ev);
421
- if (order === 'after')
677
+ function foldFleetRow(d, rid, ev, carrier, newGen) {
678
+ const r = d.rec(rid);
679
+ if (r === undefined)
422
680
  return;
423
- const endGen = row?.phase === 'ended' ? row.endCycle : undefined;
424
- const newCycle = order === 'before' || (endGen !== undefined && cycleOrder(endGen, ev) === 'before');
681
+ const row = r.row;
682
+ const fresh = () => foldUsage({ phase: 'running', tickSeen: false, announced: false, fields: fleetFields(ev) }, carrier).row;
425
683
  if (row === undefined) {
426
- const fresh = { phase: 'running', lane: 'fleet', announced: false, fields: fleetFields(ev), ...(ev.totalTokens !== undefined ? { totalTokens: ev.totalTokens } : {}), ...(ev.toolUses !== undefined ? { toolUses: ev.toolUses } : {}) };
427
- d.put(key, { row: announce(d, key, fresh) });
684
+ d.put(rid, { row: fresh() });
685
+ announce(d, rid);
428
686
  return;
429
687
  }
430
688
  if (!row.announced) {
431
- const merged = newCycle
432
- ? { phase: 'running', lane: 'fleet', announced: false, fields: fleetFields(ev), ...(ev.totalTokens !== undefined ? { totalTokens: ev.totalTokens } : {}), ...(ev.toolUses !== undefined ? { toolUses: ev.toolUses } : {}) }
433
- : { ...row, fields: { ...row.fields, ...fleetFields(ev) }, ...(ev.totalTokens !== undefined ? { totalTokens: ev.totalTokens } : {}), ...(ev.toolUses !== undefined ? { toolUses: ev.toolUses } : {}) };
434
- d.put(key, { row: announce(d, key, merged) });
689
+ d.put(rid, { row: newGen ? fresh() : foldUsage({ ...row, fields: { ...row.fields, ...fleetFields(ev) } }, carrier).row });
690
+ announce(d, rid);
435
691
  return;
436
692
  }
437
- if (newCycle) {
693
+ const key = keyOf(r);
694
+ if (newGen) {
438
695
  const fields = fleetFields(ev);
439
696
  d.deltas.push({ op: 'upsert', canonicalId: key, revived: true, fields: { ...fields, ...(row.fields.absence ? { absence: null } : {}) } });
440
- const u = usageDelta(key, undefined, ev.totalTokens, ev.toolUses);
441
- if (u !== undefined)
442
- d.deltas.push(u);
443
697
  const kept = { ...row.fields, ...fields };
444
698
  delete kept.absence;
445
- d.put(key, { row: { phase: 'running', lane: 'fleet', announced: true, fields: kept, ...(ev.totalTokens !== undefined ? { totalTokens: ev.totalTokens } : {}), ...(ev.toolUses !== undefined ? { toolUses: ev.toolUses } : {}) } });
699
+ const next = foldUsage({ phase: 'running', tickSeen: false, announced: true, fields: kept }, carrier).row;
700
+ const u = fullUsage(key, next);
701
+ if (u !== undefined)
702
+ d.deltas.push(u);
703
+ d.put(rid, { row: next });
446
704
  return;
447
705
  }
448
- if (row.phase !== 'running')
449
- return;
450
- if (row.lane === 'tick') {
451
- if (row.fields.absence) {
452
- d.deltas.push({ op: 'upsert', canonicalId: key, fields: { absence: null } });
453
- const fields = { ...row.fields };
454
- delete fields.absence;
455
- d.put(key, { row: { ...row, fields } });
456
- }
706
+ if (row.phase !== 'running') {
707
+ const u = foldUsage(row, carrier);
708
+ if (u.change !== undefined)
709
+ d.deltas.push(usageDelta(key, u.change));
710
+ d.put(rid, { row: u.row });
457
711
  return;
458
712
  }
459
713
  const changed = changedFields(row.fields, fleetFields(ev), []);
@@ -461,135 +715,105 @@ function foldFleetRow(d, ev, prior) {
461
715
  changed.absence = null;
462
716
  if (Object.keys(changed).length > 0)
463
717
  d.deltas.push({ op: 'upsert', canonicalId: key, fields: changed });
464
- const u = usageDelta(key, row, ev.totalTokens, ev.toolUses);
465
- if (u !== undefined)
466
- d.deltas.push(u);
718
+ const u = foldUsage(row, carrier);
719
+ if (u.change !== undefined)
720
+ d.deltas.push(usageDelta(key, u.change));
467
721
  const fields = { ...row.fields, ...changed };
468
722
  if (changed.absence === null)
469
723
  delete fields.absence;
470
- d.put(key, { row: { ...row, fields, ...(ev.totalTokens !== undefined ? { totalTokens: ev.totalTokens } : {}), ...(ev.toolUses !== undefined ? { toolUses: ev.toolUses } : {}) } });
724
+ d.put(rid, { row: { ...u.row, fields } });
471
725
  }
472
- function foldEnd(d, ev) {
473
- const key = ev.taskId;
474
- const rec = d.rec(key);
475
- if (endOlderThanKnown(d, ev, key, rec?.cycle))
726
+ function foldEnd(d, rid, ev) {
727
+ const r = d.rec(rid);
728
+ if (r === undefined)
476
729
  return;
477
- const row = rec?.row;
730
+ const row = r.row;
731
+ const gen = cycleEmpty(ev) ? {} : { endCycle: cycleOf(ev) };
478
732
  if (row === undefined) {
479
- d.put(key, { row: { phase: 'ended', lane: 'fleet', announced: false, isError: ev.isError, cause: 'end', ...(cycleEmpty(ev) ? {} : { endCycle: cycleOf(ev) }), ...(ev.report !== undefined ? { report: ev.report } : {}), fields: {} } });
733
+ d.put(rid, { row: { phase: 'ended', tickSeen: false, announced: false, isError: ev.isError, cause: 'end', ...gen, ...(ev.report !== undefined ? { report: ev.report } : {}), fields: {} } });
480
734
  return;
481
735
  }
482
736
  if (row.phase !== 'running')
483
737
  return;
484
738
  const fields = { ...row.fields };
485
739
  delete fields.absence;
486
- d.put(key, { row: { ...row, phase: 'ended', lane: 'fleet', isError: ev.isError, cause: 'end', ...(cycleEmpty(ev) ? {} : { endCycle: cycleOf(ev) }), ...(ev.report !== undefined ? { report: ev.report } : {}), fields } });
740
+ d.put(rid, { row: { ...row, phase: 'ended', isError: ev.isError, cause: 'end', ...gen, ...(ev.report !== undefined ? { report: ev.report } : {}), fields } });
487
741
  if (row.announced)
488
- mintTerminal(d, key, ev.isError, ev.report, 'end');
742
+ mintTerminal(d, keyOf(r), ev.isError, ev.report, 'end');
489
743
  }
490
744
  function foldSweep(d) {
491
745
  const hits = [];
492
- for (const [key, r] of d.records.entries()) {
746
+ for (const [rid, r] of d.records.entries()) {
493
747
  const row = r.row;
494
748
  if (row === undefined || !row.announced || row.phase !== 'running')
495
749
  continue;
496
750
  if (row.fields.absence)
497
751
  continue;
498
- if (row.lane === 'fleet' || r.resident === true)
752
+ if (!row.tickSeen || r.resident === true)
499
753
  continue;
500
- hits.push(key);
754
+ hits.push(rid);
501
755
  }
502
- for (const key of hits) {
503
- const row = d.rec(key)?.row;
504
- if (row === undefined)
756
+ for (const rid of hits) {
757
+ const r = d.rec(rid);
758
+ const row = r?.row;
759
+ if (r === undefined || row === undefined)
505
760
  continue;
506
- d.put(key, { row: { ...row, phase: 'ended', isError: false, cause: 'sweep' } });
507
- mintTerminal(d, key, false, undefined, 'sweep');
761
+ const isError = row.deferredEndError === true;
762
+ d.put(rid, { row: { ...row, phase: 'ended', isError, cause: 'sweep' } });
763
+ mintTerminal(d, keyOf(r), isError, undefined, 'sweep');
508
764
  }
509
765
  }
510
- function foldAbsence(d, a) {
511
- const row = d.rec(a.taskId)?.row;
512
- if (row === undefined || !row.announced || row.phase !== 'running')
766
+ function noteDeferredEnd(d, rid, isError, frameCycle, transcript) {
767
+ if (rid === undefined)
513
768
  return;
514
- const absence = { lastSeenAtMs: a.lastSeenAtMs, absentForMs: a.absentForMs };
515
- d.deltas.push({ op: 'upsert', canonicalId: a.taskId, fields: { absence } });
516
- d.put(a.taskId, { row: { ...row, fields: { ...row.fields, absence } } });
769
+ const r = d.rec(rid);
770
+ const row = r?.row;
771
+ if (r === undefined || row === undefined || row.phase !== 'running')
772
+ return;
773
+ if (cycleOrder(r.cycle, frameCycle) === 'after')
774
+ return;
775
+ if (transcript !== undefined && bindingOf(r, transcript)?.superseded === true)
776
+ return;
777
+ d.put(rid, { row: { ...row, deferredEndError: isError } });
517
778
  }
518
- function emit(d, ev, prior) {
519
- d.facts.push({ ch: 'event', ev });
520
- switch (ev.kind) {
521
- case 'tick':
522
- foldTick(d, ev);
523
- break;
524
- case 'fleet-row':
525
- foldFleetRow(d, ev, prior);
526
- break;
527
- case 'end':
528
- foldEnd(d, ev);
529
- break;
530
- default:
531
- foldSweep(d);
532
- }
533
- boundFields(d);
534
- }
535
- function identityOf(a) {
536
- return { taskId: a.to, origin: 'fleet-row', ...cycleOf(a.cycle) };
537
- }
538
- function resolve(d, wireTaskId, parentToolCallId, touch) {
539
- const byT = d.aliasGet('t', wireTaskId, touch);
540
- if (byT !== undefined)
541
- return identityOf(byT);
542
- const byP = parentToolCallId !== undefined ? d.aliasGet('p', parentToolCallId, touch) : undefined;
543
- if (byP !== undefined)
544
- return identityOf(byP);
545
- return { taskId: wireTaskId, origin: 'wire' };
546
- }
547
- function rememberResolvedWire(d, wireTaskId, id) {
548
- if (d.aliasHas('t', wireTaskId))
779
+ function foldAbsence(d, rid, a) {
780
+ const r = d.rec(rid);
781
+ const row = r?.row;
782
+ if (r === undefined || row === undefined || !row.announced || row.phase !== 'running')
549
783
  return;
550
- const c = cycleOf(id);
551
- d.aliasSet('t', wireTaskId, { to: id.taskId, ...(cycleEmpty(c) ? {} : { cycle: c }) });
552
- }
553
- function notePublishedWire(d, ev) {
554
- d.put(ev.taskId, { wire: { retired: d.rec(ev.taskId)?.wire?.retired ?? false } });
555
- if (ev.parentToolCallId !== undefined && ev.parentToolCallId.length > 0)
556
- d.aliasSet('w', ev.parentToolCallId, { to: ev.taskId });
557
- }
558
- function retireWire(d, wireId) {
559
- const w = d.rec(wireId)?.wire;
560
- if (w !== undefined)
561
- d.put(wireId, { wire: { retired: true } });
562
- const owned = d.ownedTails(wireId).filter((k) => d.rec(k)?.ownedBy?.retired === false);
563
- for (const k of owned) {
564
- const o = d.rec(k)?.ownedBy;
565
- if (o !== undefined)
566
- d.put(k, { ownedBy: { ...o, retired: true } });
567
- }
784
+ const absence = { lastSeenAtMs: a.lastSeenAtMs, absentForMs: a.absentForMs };
785
+ d.deltas.push({ op: 'upsert', canonicalId: keyOf(r), fields: { absence } });
786
+ d.put(rid, { row: { ...row, fields: { ...row.fields, absence } } });
568
787
  }
569
- function isPublishedWire(d, id) {
570
- return d.rec(id)?.wire !== undefined;
788
+ function stripCardBound(ev) {
789
+ const { cardBound: _cardBound, ...rest } = ev;
790
+ void _cardBound;
791
+ return rest;
571
792
  }
572
- function publishedWireFor(d, ev) {
573
- if (ev.transcriptId !== undefined && isPublishedWire(d, ev.transcriptId))
574
- return ev.transcriptId;
575
- if (ev.parentToolCallId !== undefined) {
576
- const u = d.aliasGet('w', ev.parentToolCallId, false)?.to;
577
- if (u !== undefined && d.rec(u)?.wire?.retired === false)
578
- return u;
579
- }
580
- return undefined;
793
+ function emitTick(d, ev) {
794
+ const found = d.find(ev.taskId);
795
+ const fr = found !== undefined ? d.rec(found) : undefined;
796
+ if (fr !== undefined && formerGeneration(fr, ev.taskId))
797
+ return;
798
+ const rid = found ?? d.create({ id: ev.taskId });
799
+ d.records.touch(rid);
800
+ const r = d.rec(rid);
801
+ if (r === undefined)
802
+ return;
803
+ const key = keyOf(r);
804
+ const plain = stripCardBound(ev);
805
+ const fact = key === ev.taskId
806
+ ? { ...plain, taskIdOrigin: 'wire' }
807
+ : { ...plain, taskId: key, wireTaskId: ev.taskId, taskIdOrigin: key === r.tail ? 'fleet-row' : 'wire' };
808
+ d.facts.push({ ch: 'event', ev: fact });
809
+ foldTick(d, rid, fact, ev.cardBound === true);
581
810
  }
582
- function wireOwnerOf(d, fleetId, current, transcriptId) {
583
- const o = d.rec(fleetId)?.ownedBy;
584
- if (o === undefined)
585
- return undefined;
586
- const newTranscript = transcriptId !== undefined && transcriptId !== (o.transcriptId ?? o.wireId);
587
- if (newTranscript || (current !== undefined && isStaleEngineAgentPanelEnd(d.rec(o.wireId)?.cycle, current))) {
588
- d.put(fleetId, { ownedBy: undefined });
589
- retireWire(d, o.wireId);
590
- return undefined;
591
- }
592
- return o.wireId;
811
+ function flushHeld(d, wireTaskId) {
812
+ const held = d.pending.get(wireTaskId);
813
+ if (held === undefined)
814
+ return;
815
+ d.pending.delete(wireTaskId);
816
+ emitTick(d, held.ev);
593
817
  }
594
818
  function ageHeld(d, except) {
595
819
  for (const [wireId, held] of [...d.pending.entries()]) {
@@ -598,116 +822,13 @@ function ageHeld(d, except) {
598
822
  const beats = held.beats + 1;
599
823
  if (beats >= MAX_HELD_WIRE_TICK_BEATS) {
600
824
  d.pending.delete(wireId);
601
- emit(d, asIsTick(d, held.ev));
825
+ emitTick(d, held.ev);
602
826
  }
603
827
  else {
604
828
  d.pending.set(wireId, { ev: held.ev, beats });
605
829
  }
606
830
  }
607
831
  }
608
- function migrateResidency(d, wireTaskId, fleetId) {
609
- if (wireTaskId !== fleetId && d.rec(wireTaskId)?.resident === true) {
610
- d.put(wireTaskId, { resident: undefined });
611
- d.put(fleetId, { resident: true });
612
- }
613
- }
614
- function stripCardBound(ev) {
615
- const { cardBound: _cardBound, ...rest } = ev;
616
- void _cardBound;
617
- return rest;
618
- }
619
- function normalizedTick(d, ev, fleetId) {
620
- migrateResidency(d, ev.taskId, fleetId);
621
- return { ...stripCardBound(ev), taskId: fleetId, wireTaskId: ev.taskId, taskIdOrigin: 'fleet-row' };
622
- }
623
- function asIsTick(d, ev) {
624
- notePublishedWire(d, ev);
625
- return { ...stripCardBound(ev), taskIdOrigin: 'wire' };
626
- }
627
- function staleWireTick(d, id) {
628
- return isStaleEngineAgentPanelEnd(id, d.rec(id.taskId)?.cycle);
629
- }
630
- function flushHeld(d, wireTaskId) {
631
- const held = d.pending.get(wireTaskId);
632
- if (held === undefined)
633
- return;
634
- d.pending.delete(wireTaskId);
635
- if (isPublishedWire(d, held.ev.taskId)) {
636
- emit(d, asIsTick(d, held.ev));
637
- return;
638
- }
639
- const id = resolve(d, held.ev.taskId, held.ev.parentToolCallId, true);
640
- if (id.origin === 'fleet-row') {
641
- if (staleWireTick(d, id))
642
- return;
643
- rememberResolvedWire(d, held.ev.taskId, id);
644
- emit(d, normalizedTick(d, held.ev, id.taskId));
645
- return;
646
- }
647
- emit(d, asIsTick(d, held.ev));
648
- }
649
- function notePanelRowRunning(d, taskId) {
650
- if (d.rec(taskId)?.running === true)
651
- return;
652
- d.put(taskId, { running: true });
653
- }
654
- function panelRowUnknownToConsumer(d, taskId) {
655
- const r = d.rec(taskId);
656
- return !d.overflowed && r?.running !== true && r?.ended === undefined;
657
- }
658
- function notePanelRowEnded(d, taskId, cycle, older) {
659
- const existing = d.rec(taskId)?.ended;
660
- if (existing !== undefined && older)
661
- return;
662
- d.put(taskId, { ended: mergeCycle(cycleOf(cycle), existing) });
663
- }
664
- function settleRowHistory(d, taskId, cycle) {
665
- d.put(taskId, { running: undefined });
666
- notePanelRowEnded(d, taskId, cycle, isStaleEngineAgentPanelEnd(cycle, d.rec(taskId)?.ended));
667
- }
668
- function endOlderThanKnown(d, end, taskId, rowCycle) {
669
- return isStaleEngineAgentPanelEnd(end, rowCycle) || isStaleEngineAgentPanelEnd(end, d.rec(taskId)?.ended);
670
- }
671
- function heldRowConsumerKey(d, tail, held) {
672
- const owner = d.rec(tail)?.ownedBy;
673
- if (owner !== undefined)
674
- return owner.wireId;
675
- return publishedWireFor(d, held) ?? tail;
676
- }
677
- function heldVerdict(d, taskId, endCycle) {
678
- const held = d.rec(taskId)?.held;
679
- if (held === undefined)
680
- return 'none';
681
- const o = cycleOrder(endCycle, held);
682
- if (o === 'before')
683
- return 'keep';
684
- if (o === 'after')
685
- return 'drop';
686
- return 'release';
687
- }
688
- function heldRowReleasesOntoSameKey(d, tail, end) {
689
- const held = d.rec(tail)?.held;
690
- if (held === undefined)
691
- return false;
692
- const rowKey = heldRowConsumerKey(d, tail, held);
693
- if (rowKey === end.taskId)
694
- return true;
695
- return rowKey === tail && held.transcriptId === end.taskId && !isPublishedWire(d, end.taskId);
696
- }
697
- function releaseHeld(d, taskId, endCycle) {
698
- const verdict = heldVerdict(d, taskId, endCycle);
699
- if (verdict === 'drop') {
700
- d.put(taskId, { held: undefined });
701
- return;
702
- }
703
- if (verdict !== 'release')
704
- return;
705
- const held = d.rec(taskId)?.held;
706
- if (held === undefined)
707
- return;
708
- d.put(taskId, { held: undefined });
709
- publish(d, held);
710
- }
711
832
  function publish(d, ev) {
712
833
  if (ev.kind === 'end' || ev.kind === 'sweep')
713
834
  ageHeld(d, ev.kind === 'sweep' ? undefined : ev.taskId);
@@ -719,65 +840,58 @@ function publish(d, ev) {
719
840
  case 'end':
720
841
  return publishEnd(d, ev);
721
842
  default:
722
- emit(d, ev);
843
+ d.facts.push({ ch: 'event', ev });
844
+ foldSweep(d);
723
845
  }
724
846
  }
725
847
  function publishFleetRow(d, ev) {
726
848
  const rowCycle = cycleOf(ev);
727
- const published = wireOwnerOf(d, ev.taskId, rowCycle, ev.transcriptId) ?? publishedWireFor(d, ev);
728
- if (published !== undefined && published !== ev.taskId) {
729
- const prev = d.rec(ev.taskId)?.ownedBy;
730
- const transcriptId = ev.transcriptId ?? prev?.transcriptId;
731
- d.put(ev.taskId, { ownedBy: { wireId: published, retired: prev?.wireId === published ? prev.retired : false, ...(transcriptId !== undefined ? { transcriptId } : {}) } });
732
- const tailAnchor = d.rec(ev.taskId)?.anchor;
733
- if (tailAnchor !== undefined && tailAnchor === (transcriptId ?? published)) {
734
- d.put(published, { anchor: tailAnchor });
735
- d.put(ev.taskId, { anchor: undefined });
736
- }
737
- const prior = d.rec(published)?.cycle;
738
- if (cycleOrder(rowCycle, prior) !== 'before')
739
- d.put(published, { cycle: cycleEmpty(rowCycle) ? undefined : rowCycle });
740
- emit(d, { ...ev, taskId: published, wireTaskId: ev.taskId, taskIdOrigin: 'wire' }, prior);
849
+ const transcript = typeof ev.transcriptId === 'string' && ev.transcriptId.length > 0 ? ev.transcriptId : undefined;
850
+ noteCard(d, ev.parentToolCallId);
851
+ const rid = bind(d, ev.taskId, 'tail', transcript, rowCycle);
852
+ d.records.touch(rid);
853
+ const r = d.rec(rid);
854
+ if (r === undefined)
855
+ return;
856
+ if (transcript !== undefined && bindingOf(r, transcript)?.superseded === true) {
741
857
  ageHeld(d, undefined);
742
858
  return;
743
859
  }
744
- const prior = d.rec(ev.taskId)?.cycle;
745
- if (!cycleEmpty(rowCycle) && cycleOrder(rowCycle, prior) !== 'before')
746
- d.put(ev.taskId, { cycle: rowCycle });
747
- const alias = { to: ev.taskId, ...(cycleEmpty(rowCycle) ? {} : { cycle: rowCycle }) };
748
- if (ev.transcriptId !== undefined && ev.transcriptId.length > 0)
749
- d.aliasSet('t', ev.transcriptId, alias);
750
- if (ev.parentToolCallId !== undefined && ev.parentToolCallId.length > 0)
751
- d.aliasSet('p', ev.parentToolCallId, alias);
752
- emit(d, ev, prior);
753
- for (const [wireId, held] of [...d.pending.entries()]) {
754
- if (wireId === ev.transcriptId || (held.ev.parentToolCallId !== undefined && held.ev.parentToolCallId === ev.parentToolCallId))
755
- flushHeld(d, wireId);
860
+ const order = cycleOrder(r.cycle, rowCycle);
861
+ const stale = order === 'after';
862
+ let newGen = false;
863
+ if (!stale) {
864
+ const endGen = r.row?.phase === 'ended' ? r.row.endCycle : undefined;
865
+ newGen = order === 'before' || (endGen !== undefined && cycleOrder(endGen, rowCycle) === 'before');
866
+ if (!newGen && transcript !== undefined && !hasCycleSeq(r.cycle) && !hasCycleSeq(rowCycle) && r.currentRun !== undefined && r.currentRun !== transcript) {
867
+ newGen = true;
868
+ const ids = (r.ids ?? []).map((b) => (b.id === r.currentRun ? { ...b, superseded: true } : b));
869
+ d.put(rid, { ids });
870
+ }
871
+ d.put(rid, {
872
+ ...(transcript !== undefined ? { currentRun: transcript } : {}),
873
+ ...(!cycleEmpty(rowCycle) ? { cycle: rowCycle } : {}),
874
+ });
756
875
  }
876
+ const key = keyOf(d.rec(rid) ?? r);
877
+ const { final: _final, ...plain } = ev;
878
+ void _final;
879
+ const fact = key === ev.taskId ? plain : { ...plain, taskId: key, wireTaskId: ev.taskId, taskIdOrigin: 'wire' };
880
+ d.facts.push({ ch: 'event', ev: fact });
881
+ if (!stale)
882
+ foldFleetRow(d, rid, fact, fleetCarrier(ev), newGen);
883
+ if (transcript !== undefined)
884
+ flushHeld(d, transcript);
885
+ flushHeld(d, ev.taskId);
757
886
  ageHeld(d, undefined);
758
887
  }
759
888
  function publishTick(d, ev) {
760
- if (isPublishedWire(d, ev.taskId)) {
889
+ noteCard(d, ev.parentToolCallId);
890
+ const rid = d.find(ev.taskId);
891
+ const r = rid !== undefined ? d.rec(rid) : undefined;
892
+ if ((r !== undefined && (r.consumerKey !== undefined || r.tail !== undefined)) || ev.cardBound === true || d.pending.has(ev.taskId)) {
761
893
  d.pending.delete(ev.taskId);
762
- emit(d, asIsTick(d, ev));
763
- return;
764
- }
765
- const id = resolve(d, ev.taskId, ev.parentToolCallId, true);
766
- if (id.origin === 'fleet-row') {
767
- d.pending.delete(ev.taskId);
768
- if (staleWireTick(d, id))
769
- return;
770
- rememberResolvedWire(d, ev.taskId, id);
771
- emit(d, normalizedTick(d, ev, id.taskId));
772
- return;
773
- }
774
- if (ev.cardBound === true) {
775
- emit(d, asIsTick(d, ev));
776
- return;
777
- }
778
- if (d.pending.has(ev.taskId)) {
779
- d.pending.delete(ev.taskId);
780
- emit(d, asIsTick(d, ev));
894
+ emitTick(d, ev);
781
895
  return;
782
896
  }
783
897
  if (d.pending.size >= MAX_HELD_WIRE_TICKS) {
@@ -787,106 +901,100 @@ function publishTick(d, ev) {
787
901
  }
788
902
  d.pending.set(ev.taskId, { ev, beats: 0 });
789
903
  }
790
- function publishEnd(d, ev) {
791
- releaseHeld(d, ev.taskId, ev);
792
- {
793
- const pre = resolve(d, ev.taskId, undefined, true);
794
- if (pre.origin === 'fleet-row' && pre.taskId !== ev.taskId) {
795
- releaseHeld(d, pre.taskId, mergeCycle(cycleOf(ev), cycleOf(pre)));
796
- }
797
- const owners = d.ownedTails(ev.taskId).filter((fleetId) => d.rec(fleetId)?.ownedBy?.retired === false);
798
- for (const fleetId of owners)
799
- releaseHeld(d, fleetId, ev);
800
- const heldMatches = [];
801
- if (d.counts.held > 0)
802
- for (const [tail, r] of d.records.entries()) {
803
- const held = r.held;
804
- if (held === undefined || tail === ev.taskId)
805
- continue;
806
- const byTranscript = typeof held.transcriptId === 'string' && held.transcriptId.length > 0 && held.transcriptId === ev.taskId;
807
- const byParent = typeof held.parentToolCallId === 'string' && held.parentToolCallId.length > 0 &&
808
- d.aliasGet('w', held.parentToolCallId, false)?.to === ev.taskId &&
809
- d.rec(ev.taskId)?.wire?.retired === false;
810
- if (byTranscript || byParent)
811
- heldMatches.push(tail);
812
- }
813
- const releasable = [];
814
- for (const tail of heldMatches) {
815
- const verdict = heldVerdict(d, tail, ev);
816
- if (verdict === 'drop')
817
- d.put(tail, { held: undefined });
818
- else if (verdict === 'release' && heldRowReleasesOntoSameKey(d, tail, ev))
819
- releasable.push(tail);
820
- }
821
- if (releasable.length === 1)
822
- releaseHeld(d, releasable[0], ev);
823
- }
824
- const wireOwner = wireOwnerOf(d, ev.taskId, ev);
825
- if (wireOwner !== undefined) {
826
- const staleA = endOlderThanKnown(d, ev, ev.taskId, d.rec(wireOwner)?.cycle) || isStaleEngineAgentPanelEnd(ev, d.rec(wireOwner)?.ended);
827
- emit(d, { ...ev, taskId: wireOwner, wireTaskId: ev.taskId, taskIdOrigin: 'wire' });
828
- if (!staleA) {
829
- retireWire(d, wireOwner);
830
- settleRowHistory(d, ev.taskId, ev);
831
- settleRowHistory(d, wireOwner, ev);
832
- }
904
+ function releaseHeld(d, rid, endCycle) {
905
+ const held = d.rec(rid)?.held;
906
+ if (held === undefined)
833
907
  return;
834
- }
835
- if (isPublishedWire(d, ev.taskId)) {
836
- flushHeld(d, ev.taskId);
837
- const ownedFleetIds = d.ownedTails(ev.taskId).filter((fleetId) => !endOlderThanKnown(d, ev, fleetId, d.rec(ev.taskId)?.cycle));
838
- const alias = d.aliasGet('t', ev.taskId, false);
839
- if (alias !== undefined && !endOlderThanKnown(d, ev, alias.to, alias.cycle) && !ownedFleetIds.includes(alias.to))
840
- ownedFleetIds.push(alias.to);
841
- emit(d, ev);
842
- retireWire(d, ev.taskId);
843
- if (!isStaleEngineAgentPanelEnd(ev, d.rec(ev.taskId)?.ended))
844
- settleRowHistory(d, ev.taskId, ev);
845
- for (const fleetId of ownedFleetIds)
846
- settleRowHistory(d, fleetId, ev);
908
+ const o = cycleOrder(endCycle, held);
909
+ if (o === 'before')
847
910
  return;
848
- }
849
- const id = resolve(d, ev.taskId, undefined, true);
850
- if (id.origin === 'fleet-row' && id.taskId !== ev.taskId) {
851
- flushHeld(d, ev.taskId);
852
- migrateResidency(d, ev.taskId, id.taskId);
853
- const effectiveEnd = mergeCycle(cycleOf(ev), cycleOf(id));
854
- const staleC = endOlderThanKnown(d, effectiveEnd, id.taskId, d.rec(id.taskId)?.cycle);
855
- emit(d, { ...ev, taskId: id.taskId, wireTaskId: ev.taskId, taskIdOrigin: 'fleet-row', ...effectiveEnd });
856
- if (!staleC)
857
- settleRowHistory(d, id.taskId, effectiveEnd);
911
+ d.put(rid, { held: undefined });
912
+ if (o === 'after')
858
913
  return;
859
- }
914
+ publish(d, held);
915
+ }
916
+ function settle(d, rid, cycle) {
917
+ const r = d.rec(rid);
918
+ if (r === undefined)
919
+ return;
920
+ const older = r.ended !== undefined && isStaleEngineAgentPanelEnd(cycle, r.ended);
921
+ d.put(rid, { running: undefined, ended: older ? r.ended : mergeCycle(cycleOf(cycle), r.ended) });
922
+ }
923
+ function publishEnd(d, ev) {
924
+ const pre = d.find(ev.taskId);
925
+ const pr = pre !== undefined ? d.rec(pre) : undefined;
926
+ if (pre !== undefined && pr !== undefined)
927
+ releaseHeld(d, pre, frameCycleOn(pr, ev.taskId, ev));
860
928
  flushHeld(d, ev.taskId);
861
- const staleD = endOlderThanKnown(d, ev, ev.taskId, d.rec(ev.taskId)?.cycle);
862
- emit(d, ev);
863
- retireWire(d, ev.taskId);
864
- if (!staleD)
865
- settleRowHistory(d, ev.taskId, ev);
929
+ const found = d.find(ev.taskId);
930
+ const r0 = found !== undefined ? d.rec(found) : undefined;
931
+ if (r0 !== undefined && bindingOf(r0, ev.taskId)?.superseded === true)
932
+ return;
933
+ const effective = frameCycleOn(r0, ev.taskId, ev);
934
+ const rid = found ?? d.create({ id: ev.taskId });
935
+ d.records.touch(rid);
936
+ const r = d.rec(rid);
937
+ if (r === undefined)
938
+ return;
939
+ const stale = isStaleEngineAgentPanelEnd(effective, r.cycle) || isStaleEngineAgentPanelEnd(effective, r.ended);
940
+ const key = keyOf(r);
941
+ const fact = {
942
+ ...ev,
943
+ ...(key !== ev.taskId ? { taskId: key, wireTaskId: ev.taskId, taskIdOrigin: key === r.tail ? 'fleet-row' : 'wire' } : {}),
944
+ ...effective,
945
+ };
946
+ d.facts.push({ ch: 'event', ev: fact });
947
+ if (stale)
948
+ return;
949
+ foldEnd(d, rid, fact);
950
+ settle(d, rid, effective);
866
951
  }
867
952
  function publishAbsence(d, a) {
868
- const owner = wireOwnerOf(d, a.taskId);
869
- const ev = owner !== undefined ? { ...a, taskId: owner, wireTaskId: a.taskId } : a;
953
+ const rid = d.find(a.taskId);
954
+ const r = rid !== undefined ? d.rec(rid) : undefined;
955
+ const key = r !== undefined ? keyOf(r) : a.taskId;
956
+ const ev = key !== a.taskId ? { ...a, taskId: key, wireTaskId: a.taskId } : a;
870
957
  d.facts.push({ ch: 'absence', absence: ev });
871
- foldAbsence(d, ev);
872
- }
873
- function clearResidentByWire(d, wireTaskId, cycle) {
874
- d.put(wireTaskId, { resident: undefined });
875
- const owner = d.rec(wireTaskId)?.ownedBy;
876
- if (owner !== undefined && !(cycle !== undefined && isStaleEngineAgentPanelEnd(cycle, d.rec(owner.wireId)?.cycle)))
877
- d.put(owner.wireId, { resident: undefined });
878
- const id = resolve(d, wireTaskId, undefined, true);
879
- if (id.taskId === wireTaskId)
958
+ if (rid !== undefined)
959
+ foldAbsence(d, rid, ev);
960
+ }
961
+ function setResident(d, id, resident) {
962
+ const rid = d.find(id);
963
+ if (resident)
964
+ d.put(rid ?? d.create({ id }), { resident: true });
965
+ else if (rid !== undefined)
966
+ d.put(rid, { resident: undefined });
967
+ }
968
+ function clearResidentByWire(d, id, cycle) {
969
+ const rid = d.find(id);
970
+ const r = rid !== undefined ? d.rec(rid) : undefined;
971
+ if (rid === undefined || r === undefined)
972
+ return;
973
+ if (bindingOf(r, id)?.superseded === true)
880
974
  return;
881
- if (isStaleEngineAgentPanelEnd(id, d.rec(id.taskId)?.cycle))
975
+ if (isStaleEngineAgentPanelEnd(frameCycleOn(r, id, cycleOf(cycle)), r.cycle))
882
976
  return;
883
- d.put(id.taskId, { resident: undefined });
977
+ d.put(rid, { resident: undefined });
884
978
  }
885
979
  function currentToolKeyOf(ct) {
886
980
  if (!ct || typeof ct.toolName !== 'string' || ct.toolName.length === 0)
887
981
  return undefined;
888
982
  return `${ct.toolName}\u0000${ct.target ?? ''}`;
889
983
  }
984
+ function sameGeneration(r, frameCycle, transcript) {
985
+ if (cycleOrder(r.cycle, frameCycle) === 'before')
986
+ return false;
987
+ if (r.row?.endCycle !== undefined && cycleOrder(r.row.endCycle, frameCycle) === 'before')
988
+ return false;
989
+ if (!hasCycleSeq(r.cycle) && transcript !== undefined && r.currentRun !== undefined && r.currentRun !== transcript)
990
+ return false;
991
+ return true;
992
+ }
993
+ function knownToProcess(r, frameCycle) {
994
+ if (r === undefined)
995
+ return false;
996
+ return r.running === true || r.row?.announced === true || (r.ended !== undefined && cycleOrder(r.ended, frameCycle) !== 'before');
997
+ }
890
998
  function project(d, sessionKey, rows, nowMs) {
891
999
  const seen = d.session(sessionKey);
892
1000
  const present = new Set();
@@ -906,7 +1014,9 @@ function project(d, sessionKey, rows, nowMs) {
906
1014
  const currentTool = currentToolKeyOf(row.currentTool) !== undefined ? row.currentTool : undefined;
907
1015
  const currentToolKey = currentToolKeyOf(row.currentTool);
908
1016
  const prev = seen.get(taskId);
909
- const prevCycle = prev !== undefined ? (d.rec(taskId)?.cycle ?? {}) : undefined;
1017
+ const tailRid = d.find(taskId);
1018
+ const tailRec = tailRid !== undefined ? d.rec(tailRid) : undefined;
1019
+ const prevCycle = prev !== undefined ? (tailRec?.cycle ?? {}) : undefined;
910
1020
  const order = prev !== undefined ? cycleOrder(frameCycle, prevCycle) : 'unknown';
911
1021
  if (order === 'before')
912
1022
  continue;
@@ -930,30 +1040,49 @@ function project(d, sessionKey, rows, nowMs) {
930
1040
  ...knownFields,
931
1041
  };
932
1042
  if (isSdkFleetTaskTerminal(status)) {
933
- const wireEnded = transcriptId !== undefined ? d.rec(transcriptId)?.ended : undefined;
934
- const endedViaWire = wireEnded !== undefined && cycleOrder(wireEnded, frameCycle) !== 'before';
935
- const newbornTerminal = prev === undefined && panelRowUnknownToConsumer(d, taskId) && !endedViaWire;
1043
+ const viaRun = transcriptId !== undefined ? d.find(transcriptId) : undefined;
1044
+ const runAny = viaRun !== undefined ? d.rec(viaRun) : undefined;
1045
+ const runRec = runAny !== undefined && (runAny.tail === undefined || runAny.tail === taskId) ? runAny : undefined;
1046
+ const knownHere = knownToProcess(tailRec, frameCycle) || knownToProcess(runRec, frameCycle);
1047
+ const cardSeen = parentToolCallId !== undefined && d.cards.has(parentToolCallId);
1048
+ const newbornTerminal = prev === undefined && !d.overflowed && !knownHere && !cardSeen;
936
1049
  const settledThisCycle = prev?.settled === true && !rowNewer;
937
- const endedRec = prev === undefined ? d.rec(taskId)?.ended : undefined;
1050
+ const settledRec = [tailRec, runRec].find((r) => r?.row?.announced === true) ?? tailRec;
1051
+ const endedRec = prev === undefined ? settledRec?.ended : undefined;
938
1052
  if (endedRec !== undefined && cycleOrder(frameCycle, endedRec) === 'before')
939
1053
  continue;
940
1054
  const endedSameCycle = endedRec !== undefined && cycleOrder(endedRec, frameCycle) !== 'before';
1055
+ const target = tailRec ?? runRec;
1056
+ const gateOwned = target?.row?.phase === 'running' && target.row.gateBound === true && sameGeneration(target, frameCycle, transcriptId);
1057
+ const final = finalityOf(tokens, toolUses);
1058
+ const terminalRow = final !== undefined ? { ...base, final } : base;
941
1059
  if (newbornTerminal) {
942
- d.put(taskId, { held: base });
1060
+ d.put(bind(d, taskId, 'tail', transcriptId, frameCycle), { held: terminalRow });
1061
+ }
1062
+ else if (settledThisCycle) {
1063
+ const more = (tokens !== undefined && prev?.tokens !== tokens) || (toolUses !== undefined && prev?.toolUses !== toolUses);
1064
+ if (more && tailRid !== undefined && tailRec?.held !== undefined)
1065
+ d.put(tailRid, { held: terminalRow });
1066
+ else if (more)
1067
+ publish(d, terminalRow);
943
1068
  }
944
- else if (!settledThisCycle) {
945
- if (rowNewer ||
1069
+ else {
1070
+ if (tailRid === undefined ||
1071
+ final !== undefined ||
1072
+ rowNewer ||
946
1073
  cycleKeysChanged(prevCycle, frameCycle) ||
947
- (tokens !== undefined && prev?.tokens !== tokens) ||
948
- (toolUses !== undefined && prev?.toolUses !== toolUses) ||
949
1074
  (transcriptId !== undefined && prev?.transcriptId !== transcriptId) ||
950
1075
  (parentToolCallId !== undefined && prev?.parentToolCallId !== parentToolCallId)) {
951
- publish(d, base);
1076
+ publish(d, terminalRow);
952
1077
  }
953
- if (!endedSameCycle)
1078
+ if (!endedSameCycle && !gateOwned)
954
1079
  publish(d, panelEndFact(taskId, isSdkFleetTaskTerminalNotSuccess(status), known));
1080
+ else if (!endedSameCycle)
1081
+ noteDeferredEnd(d, d.find(taskId), isSdkFleetTaskTerminalNotSuccess(status), frameCycle, transcriptId);
955
1082
  }
956
- d.put(taskId, { cycle: cycleEmpty(known) ? undefined : known });
1083
+ const rid = d.find(taskId);
1084
+ if (rid !== undefined && !cycleEmpty(known))
1085
+ d.put(rid, { cycle: known });
957
1086
  seen.set(taskId, {
958
1087
  status,
959
1088
  tokens: knownTokens,
@@ -968,9 +1097,10 @@ function project(d, sessionKey, rows, nowMs) {
968
1097
  });
969
1098
  continue;
970
1099
  }
971
- if (prev !== undefined && prev.settled && order === 'same' && d.rec(taskId)?.held !== undefined)
1100
+ if (prev !== undefined && prev.settled && order === 'same' && tailRec?.held !== undefined)
972
1101
  continue;
973
1102
  if (!prev ||
1103
+ tailRid === undefined ||
974
1104
  prev.settled ||
975
1105
  prev.absentReportedAtMs !== undefined ||
976
1106
  prev.status !== status ||
@@ -980,11 +1110,14 @@ function project(d, sessionKey, rows, nowMs) {
980
1110
  (parentToolCallId !== undefined && prev.parentToolCallId !== parentToolCallId) ||
981
1111
  cycleKeysChanged(prevCycle, frameCycle) ||
982
1112
  (currentToolKey !== undefined && prev.currentToolKey !== currentToolKey)) {
983
- notePanelRowRunning(d, taskId);
984
- d.put(taskId, { held: undefined });
985
1113
  publish(d, { ...base, ...(currentTool !== undefined ? { currentTool } : {}) });
1114
+ const rid = d.find(taskId);
1115
+ if (rid !== undefined)
1116
+ d.put(rid, { running: true, held: undefined });
986
1117
  }
987
- d.put(taskId, { cycle: cycleEmpty(known) ? undefined : known });
1118
+ const rid = d.find(taskId);
1119
+ if (rid !== undefined && !cycleEmpty(known))
1120
+ d.put(rid, { cycle: known });
988
1121
  seen.set(taskId, {
989
1122
  status,
990
1123
  tokens: knownTokens,
@@ -1036,10 +1169,12 @@ export function stepPanelFrame(state, frame) {
1036
1169
  case 'fleet-rows-reset':
1037
1170
  d.dropSessions(frame.sessionKey);
1038
1171
  if (frame.sessionKey === undefined) {
1039
- for (const [k, r] of [...d.records.entries()]) {
1172
+ for (const [rid, r] of [...d.records.entries()]) {
1040
1173
  if (r.running !== undefined || r.ended !== undefined || r.held !== undefined)
1041
- d.put(k, { running: undefined, ended: undefined, held: undefined });
1174
+ d.put(rid, { running: undefined, ended: undefined, held: undefined });
1042
1175
  }
1176
+ for (const [k] of [...d.cards.entries()])
1177
+ d.cards.delete(k);
1043
1178
  d.overflowed = false;
1044
1179
  }
1045
1180
  break;
@@ -1047,17 +1182,17 @@ export function stepPanelFrame(state, frame) {
1047
1182
  publishAbsence(d, frame.absence);
1048
1183
  break;
1049
1184
  case 'resident':
1050
- d.put(frame.taskId, { resident: frame.resident ? true : undefined });
1185
+ setResident(d, frame.taskId, frame.resident);
1051
1186
  break;
1052
1187
  case 'resident-clear-wire':
1053
1188
  clearResidentByWire(d, frame.taskId, frame.cycle);
1054
1189
  break;
1055
1190
  case 'anchor':
1056
1191
  if (frame.taskId && frame.transcriptId)
1057
- d.put(anchorKeyOf(d, frame.taskId), { anchor: frame.transcriptId });
1192
+ d.put(bind(d, frame.taskId, 'unknown', frame.transcriptId, undefined), { anchor: frame.transcriptId });
1058
1193
  break;
1059
1194
  }
1060
- boundFields(d);
1195
+ boundRecords(d);
1061
1196
  return { state: d.freeze(), deltas: d.deltas, facts: d.facts };
1062
1197
  }
1063
1198
  export function reducePanelFrame(state, frame) {
@@ -1066,12 +1201,18 @@ export function reducePanelFrame(state, frame) {
1066
1201
  }
1067
1202
  export function panelRowSnapshot(state) {
1068
1203
  const out = [];
1069
- for (const [key, r] of impl(state).records.entries()) {
1204
+ const shown = [];
1205
+ for (const [, r] of impl(state).records.entries())
1206
+ if (r.row?.announced === true)
1207
+ shown.push(r);
1208
+ shown.sort((a, b) => (a.announceSeq ?? 0) - (b.announceSeq ?? 0));
1209
+ for (const r of shown) {
1070
1210
  const row = r.row;
1071
- if (row === undefined || !row.announced)
1211
+ if (row === undefined)
1072
1212
  continue;
1213
+ const key = keyOf(r);
1073
1214
  out.push({ op: 'upsert', canonicalId: key, created: true, fields: { ...row.fields } });
1074
- const u = usageDelta(key, undefined, row.totalTokens, row.toolUses);
1215
+ const u = fullUsage(key, row);
1075
1216
  if (u !== undefined)
1076
1217
  out.push(u);
1077
1218
  if (row.phase === 'ended')
@@ -1079,57 +1220,47 @@ export function panelRowSnapshot(state) {
1079
1220
  }
1080
1221
  return out;
1081
1222
  }
1082
- export function panelResolveTaskId(state, wireTaskId, parentToolCallId) {
1223
+ function recordOfId(state, id) {
1083
1224
  const s = impl(state);
1084
- const byT = s.alias.get(`t:${wireTaskId}`);
1085
- if (byT !== undefined)
1086
- return identityOf(byT);
1087
- const byP = parentToolCallId !== undefined ? s.alias.get(`p:${parentToolCallId}`) : undefined;
1088
- if (byP !== undefined)
1089
- return identityOf(byP);
1090
- return { taskId: wireTaskId, origin: 'wire' };
1225
+ const rid = s.index.get(id);
1226
+ return rid !== undefined ? s.records.get(rid) : undefined;
1091
1227
  }
1092
- export function panelIsResident(state, taskId) {
1093
- return impl(state).records.get(taskId)?.resident === true;
1228
+ export function panelResolveTaskId(state, wireTaskId) {
1229
+ const r = recordOfId(state, wireTaskId);
1230
+ if (r?.tail === undefined)
1231
+ return { taskId: wireTaskId, origin: 'wire' };
1232
+ return { taskId: r.tail, origin: 'fleet-row', ...cycleOf(bindingOf(r, wireTaskId)?.gen) };
1094
1233
  }
1095
- function anchorKeyOf(d, taskId) {
1096
- const o = d.rec(taskId)?.ownedBy;
1097
- return o !== undefined && !o.retired ? o.wireId : taskId;
1234
+ export function panelIsResident(state, taskId) {
1235
+ return recordOfId(state, taskId)?.resident === true;
1098
1236
  }
1099
1237
  export function panelAnchorOf(state, taskId) {
1100
- const recs = impl(state).records;
1101
- const own = recs.get(taskId);
1102
- if (own?.anchor !== undefined)
1103
- return own.anchor;
1104
- return own?.ownedBy !== undefined ? recs.get(own.ownedBy.wireId)?.anchor : undefined;
1238
+ return recordOfId(state, taskId)?.anchor;
1105
1239
  }
1106
1240
  export function panelPresenceSize(state, sessionKey) {
1107
1241
  return impl(state).sessions.get(sessionKey)?.size ?? 0;
1108
1242
  }
1109
1243
  export function panelClearIdentity(state) {
1110
1244
  const d = new Step(impl(state));
1111
- for (const [k] of [...d.alias.entries()])
1112
- d.alias.delete(k);
1113
- d.counts.alias = { t: 0, p: 0, w: 0 };
1245
+ for (const [k] of [...d.index.entries()])
1246
+ d.index.delete(k);
1114
1247
  for (const [k] of [...d.pending.entries()])
1115
1248
  d.pending.delete(k);
1116
- for (const [k, r] of [...d.records.entries()]) {
1117
- if (r.cycle !== undefined || r.wire !== undefined || r.ownedBy !== undefined)
1118
- d.put(k, { cycle: undefined, wire: undefined, ownedBy: undefined });
1119
- }
1249
+ for (const [k] of [...d.cards.entries()])
1250
+ d.cards.delete(k);
1120
1251
  return d.freeze();
1121
1252
  }
1122
1253
  export function panelClearAnchors(state) {
1123
1254
  const d = new Step(impl(state));
1124
- for (const [k, r] of [...d.records.entries()])
1255
+ for (const [rid, r] of [...d.records.entries()])
1125
1256
  if (r.anchor !== undefined)
1126
- d.put(k, { anchor: undefined });
1257
+ d.put(rid, { anchor: undefined });
1127
1258
  return d.freeze();
1128
1259
  }
1129
1260
  export function panelClearRows(state) {
1130
1261
  const d = new Step(impl(state));
1131
- for (const [k, r] of [...d.records.entries()])
1262
+ for (const [rid, r] of [...d.records.entries()])
1132
1263
  if (r.row !== undefined)
1133
- d.put(k, { row: undefined });
1264
+ d.put(rid, { row: undefined });
1134
1265
  return d.freeze();
1135
1266
  }