@volter/supercode-orchestrator 0.4.68 → 0.4.70

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.
@@ -632,7 +632,12 @@ function launchPane(board, task, runId, lane, fleet, { input = null, slot = 'wor
632
632
  let session = null;
633
633
  let replaced = null;
634
634
  if (prev?.forgotten) replaced = { session_id: prev.session_id, why: 'the workflow let it go' };
635
- else if (prev && prev.machine === machine) {
635
+ else if (prev && (prev.harness ?? 'claude-code') !== harness) {
636
+ // the card was reassigned to a lane of another harness: that harness starts it fresh (the card's text and thread
637
+ // are its context), and the last session, if still open, is closed so two harnesses never work one card
638
+ if (prev.pane && !prev.closed_at) stopSession(board, prev);
639
+ replaced = { session_id: prev.session_id, why: `the card's lane runs ${harness}, not ${prev.harness ?? 'claude-code'}`, letGo: true };
640
+ } else if (prev && prev.machine === machine) {
636
641
  // a session the board closed, or one whose close its own command asked for (the next tick's sweep closes that
637
642
  // run's pane), is not kept, whatever a fleet reading taken before the close still lists
638
643
  if (!prev.closed_at && !prev.close_requested && sessionAlive(fleet, prev)) {
@@ -656,8 +661,8 @@ function launchPane(board, task, runId, lane, fleet, { input = null, slot = 'wor
656
661
  } else replaced = { session_id: prev.session_id, why: 'its resume never came up' };
657
662
  } else if (prev) replaced = { session_id: prev.session_id, why: `the card moved from ${prev.machine} to ${machine}` };
658
663
  // a card keeps its context: a slot's session that cannot be kept or resumed stops the launch, and only a session the
659
- // workflow let go (`forget_session`) is replaced by a new one
660
- if (replaced && !prev?.forgotten) {
664
+ // workflow let go (`forget_session`) or its manager did (a reassignment to another harness's lane) is replaced
665
+ if (replaced && !prev?.forgotten && !replaced.letGo) {
661
666
  const failed = new Error(`session ${replaced.session_id} (${slot}) could not be continued: ${replaced.why}. The board keeps a card's context and starts a new session only when the workflow lets this one go`);
662
667
  failed.resumeFailed = { session_id: replaced.session_id, slot, why: replaced.why };
663
668
  throw failed;
package/board.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  // The home's board, dispatched while the orchestrator serves the home (docs/architecture/orchestrator.md §2.9,
2
2
  // docs/plans/hermes-compat.md row 14). The board and its dispatcher are supercode's own (`board/`): Hermes Kanban's
3
3
  // format and lifecycle, each profile's lane decided by its `worker` in the IR. Where a Hermes gateway would run
4
- // its dispatcher, the daemon runs this one the same way: gated by `kanban.dispatch_in_gateway` (and
5
- // `HERMES_KANBAN_DISPATCH_IN_GATEWAY`), holding the board's one-dispatcher lock (`kanban/.dispatcher.lock`, the
6
- // lock Hermes's gateways take, so the two never dispatch one board together), one tick every
7
- // `kanban.dispatch_interval_seconds` (60, at least 1), the first after five seconds. Each tick runs as
4
+ // its dispatcher, the daemon runs this one the same way: when the board's workflow says so (its `dispatch.serve`),
5
+ // holding the board's one-dispatcher lock (`kanban/.dispatcher.lock`, the
6
+ // lock Hermes's gateways take, so the two never dispatch one board together), one tick every `dispatch.tick` seconds
7
+ // of the workflow (at least 1), the first after five seconds. Each tick runs as
8
8
  // `workflow dispatch` in a child process: a tick waits on supercode (the fleet, launches, mail), and the daemon's
9
9
  // own loop never does.
10
10
  import { spawn } from 'node:child_process';
@@ -34,8 +34,6 @@ function dispatchOnce(root) {
34
34
 
35
35
  /** Start the board's dispatcher for the home at `root`; answers `{ tick, stop }`, or null when it does not dispatch. */
36
36
  export async function startBoard({ root, orchestration = null, log = () => {}, adapters = {}, wake = null }) {
37
- const off = String(process.env.HERMES_KANBAN_DISPATCH_IN_GATEWAY ?? '').trim().toLowerCase();
38
- if (['0', 'false', 'no', 'off'].includes(off)) { log('info', 'board: not dispatched (HERMES_KANBAN_DISPATCH_IN_GATEWAY)'); return null; }
39
37
  // whether and how often the served home dispatches is the board workflow's (`dispatch.serve`, `dispatch.tick`)
40
38
  let entry;
41
39
  try { entry = workflowEntry(orchestration); } catch (error) { log('warn', `board: not dispatched: ${error.message}`); return null; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.4.68",
3
+ "version": "0.4.70",
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": {