@volter/supercode-orchestrator 0.5.145 → 0.5.147

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 (2) hide show
  1. package/board/dispatch.mjs +13 -3
  2. package/package.json +2 -2
@@ -2626,6 +2626,12 @@ function sessionRecord(db) {
2626
2626
  return { held, latest };
2627
2627
  }
2628
2628
 
2629
+ /**
2630
+ * Whether the board's own record says the session at `address` has ended: the latest run that names it closed or
2631
+ * released it, and no unended or current run works in it. An agent's address, or a session no run names, is never one.
2632
+ */
2633
+ const recordedEnded = ({ held, latest }, address) => Boolean(sessionAt(address)) && !held.has(address) && Boolean(latest.get(address)?.session.close_confirmed_at);
2634
+
2629
2635
  /**
2630
2636
  * The worker subscriptions of sessions that have ended, removed in one transaction, with one notice_unsubscribed event
2631
2637
  * per session naming its cards. A session has ended when no unended or current run works in it, the fleet does not list
@@ -2669,10 +2675,13 @@ async function endWorkerSubscriptions(board, fleet, report) {
2669
2675
  * Each subscriber's notices, filed in its mailbox (D138 step 6, D140): the dispatcher's job ends at the filing, a local
2670
2676
  * write under the notice's fixed key; the mailbox delivers it to the session, on this machine or through Teams on
2671
2677
  * another. Each subscription's notices go in order, and its cursor moves past a notice once it is filed (or passed
2672
- * over); a filing that failed here leaves the cursor before it, and the next pass files it.
2678
+ * over); a filing that failed here leaves the cursor before it, and the next pass files it. A session the board's own
2679
+ * record says has ended (recordedEnded) is filed nothing, in any role, until it is read running again: its cursor
2680
+ * stays, so a session resumed later is told what it missed. A pass with no fleet reading files it nothing either.
2673
2681
  */
2674
2682
  async function notify(board, fleet, report, entry) {
2675
2683
  await endWorkerSubscriptions(board, fleet, report);
2684
+ const record = view(board, (db) => sessionRecord(db));
2676
2685
  for (const sub of subscriptions(board.db).filter((s) => s.platform === 'supercode')) {
2677
2686
  if (stopping) break;
2678
2687
  if (sub.delivery_metadata?.dependent_card && sub.delivery_metadata.waiting_recipient) continue;
@@ -2680,12 +2689,13 @@ async function notify(board, fleet, report, entry) {
2680
2689
  // a session the fleet does not list this pass is told next pass: one reading is not a loss (a loaded box drops
2681
2690
  // sessions from a read, and a dropped subscription never came back), and a session that is replaced on its card
2682
2691
  // has its subscription moved when the new one starts
2683
- if (role !== 'creator' && fleet.ok) {
2692
+ const ended = recordedEnded(record, sub.chat_id);
2693
+ if ((role !== 'creator' || ended) && fleet.ok) {
2684
2694
  const alive = await subscriberAlive(fleet, sub.chat_id);
2685
2695
  if (alive === false) continue;
2686
2696
  // unknown is not absent: its notices wait, and the wait is said, until its liveness can be read
2687
2697
  if (alive === null) { report.undelivered.push([sub.task_id, sub.chat_id, 'its liveness could not be read; its notices wait until it can be']); continue; }
2688
- }
2698
+ } else if (ended) continue; // no fleet reading: nothing is filed unread to a session recorded as ended
2689
2699
  const kinds = heardBy(entry, role);
2690
2700
  if (!kinds.length) continue;
2691
2701
  const events = board.db.prepare(`SELECT id, kind, payload, created_at, run_id FROM task_events WHERE task_id = ? AND id > ? AND kind IN (${kinds.map(() => '?').join(', ')}) ORDER BY id`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.5.145",
3
+ "version": "0.5.147",
4
4
  "type": "module",
5
5
  "description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
6
6
  "exports": {
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@volter/supercode-harness-sdk": "^0.3.91",
28
- "@volter/teams": "0.2.59",
28
+ "@volter/teams": "0.2.60",
29
29
  "@volter/ztrack": "^2.4.23",
30
30
  "yaml": "^2.9.0"
31
31
  },