@adrrr/tarmac 0.4.1 → 0.6.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.
package/dist/map.js CHANGED
@@ -3,6 +3,12 @@
3
3
  // A view over the fleet `buildFleet` already produced. It opens no second source: every
4
4
  // field below is derived from a row that is already on the page as a table line.
5
5
  import { isWaiting } from './sessions.js';
6
+ /**
7
+ * What a berth is labelled when the source published no working directory for it. In the
8
+ * vocabulary the dials already use for a reading they do not have (`not chained`, `no turn
9
+ * yet`): a kind of nothing, named, rather than an empty frame that reads as a bug.
10
+ */
11
+ const NO_DIRECTORY = 'no directory';
6
12
  /**
7
13
  * How recently a snapshot must have landed for its node to pulse. Two of the page's poll
8
14
  * intervals (5s): a session whose terminal keeps drawing frames keeps its heartbeat across
@@ -13,18 +19,20 @@ import { isWaiting } from './sessions.js';
13
19
  */
14
20
  export const PULSE_WITHIN_MS = 10_000;
15
21
  /**
16
- * Where an agent is placed, and why it is a placement rather than a link.
22
+ * Where a node goes, and why that is a grouping rather than a link.
17
23
  *
18
24
  * `claude agents --json` prints interactive and background sessions in one array, and
19
25
  * publishes nothing that ties an agent to whoever dispatched it. The working directory is
20
- * the only field both carry, so it is what an agent is placed BY — it lands next to the
21
- * session sharing its directory, and nothing is ever nested inside anything. Nesting would
22
- * assert a parentage the source does not contain, and it would let this page show a smaller
23
- * fleet than the table beside it.
26
+ * the only field both carry, so it is the only thing nodes are grouped BY — they share a
27
+ * berth, and nothing is ever nested inside anything. Nesting would assert a parentage the
28
+ * source does not contain, and it would let this page show a smaller fleet than the table
29
+ * beside it.
24
30
  *
25
- * The agents are gathered separately because the fleet sorts busy sessions first, so one can
26
- * arrive before the session it belongs beside. An agent whose directory matches no session
27
- * keeps a node of its own, at the end.
31
+ * One pass, in the fleet's own order, and each berth takes its place at its FIRST node: the
32
+ * rank that lifts a session halted on a human above everything else lifts the frame around it
33
+ * too, whether the node that earned it is a session or an agent. An agent whose directory
34
+ * matches no session is a berth of its own, ordered like any other — being last was the flat
35
+ * grid's arrangement of it, never the data's.
28
36
  */
29
37
  export function buildMap({ rows }, { pulseWithinMs = PULSE_WITHIN_MS } = {}) {
30
38
  // Whether this fleet still speaks the kind we know. If NOTHING calls itself `interactive`,
@@ -53,31 +61,30 @@ export function buildMap({ rows }, { pulseWithinMs = PULSE_WITHIN_MS } = {}) {
53
61
  row.snapshotAgeMs <= pulseWithinMs,
54
62
  };
55
63
  };
56
- const agents = rows.filter((r) => roleOf(r) === 'agent');
57
- const placed = new Set();
58
- const seen = new Set();
59
- const nodes = [];
64
+ const berths = [];
65
+ const byCwd = new Map();
60
66
  for (const r of rows) {
61
- if (roleOf(r) !== 'session')
62
- continue;
63
- nodes.push(node(r));
64
- // Only the first session of a directory collects them, or two sessions in one checkout
65
- // would each grow a copy of the same agents.
66
- if (r.cwd === null || seen.has(r.cwd))
67
- continue;
68
- seen.add(r.cwd);
69
- for (const a of agents) {
70
- // Two directories nobody could read are not the same directory.
71
- if (a.cwd === null || a.cwd !== r.cwd)
72
- continue;
73
- nodes.push(node(a));
74
- placed.add(a);
67
+ const n = node(r);
68
+ // Two directories nobody could read are not the same directory, so an absent cwd joins no
69
+ // key: it opens a berth of its own every time, which is the one honest frame around it.
70
+ // Absent in both its shapes `readSessions` carries a `cwd` of `''` through verbatim, and
71
+ // one module down that empty string is already read as no directory at all (`project` comes
72
+ // out null). Keyed on it, every such node shared a frame captioned "no directory": the one
73
+ // claim this shape refuses, made by the nodes that can least support it.
74
+ let berth = !r.cwd ? undefined : byCwd.get(r.cwd);
75
+ if (berth === undefined) {
76
+ // The project, the directory itself, then the words — and the middle one is not a page
77
+ // that prints paths. `path.basename` answers the empty string for exactly one directory,
78
+ // the root, so a fleet with a session in `/` had a project of `''`: not the absent cwd
79
+ // above, and no name either. The fallback names it `/`, which is what was read.
80
+ berth = { label: r.project || r.cwd || NO_DIRECTORY, sessions: [], agents: [] };
81
+ berths.push(berth);
82
+ if (r.cwd)
83
+ byCwd.set(r.cwd, berth);
75
84
  }
85
+ (n.role === 'session' ? berth.sessions : berth.agents).push(n);
76
86
  }
77
- for (const a of agents)
78
- if (!placed.has(a))
79
- nodes.push(node(a));
80
- return { nodes };
87
+ return { berths };
81
88
  }
82
89
  /**
83
90
  * The kind a terminal calls itself, and the anchor this module reasons from. A background