@sagmans/dsh-tui 0.7.0 → 0.8.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 (59) hide show
  1. package/.agents/skills/dsh-tui-update-models/SKILL.md +95 -17
  2. package/.agents/skills/dsh-tui-update-models/references/model-wiring.md +158 -28
  3. package/.agents/skills/dsh-tui-update-models/scripts/dump-model-catalog.mjs +152 -16
  4. package/README.md +55 -22
  5. package/lib/herdr/client.d.ts +8 -0
  6. package/lib/herdr/client.d.ts.map +1 -1
  7. package/lib/herdr/client.js +13 -1
  8. package/lib/herdr/client.js.map +1 -1
  9. package/lib/herdr/constants.d.ts +18 -0
  10. package/lib/herdr/constants.d.ts.map +1 -1
  11. package/lib/herdr/constants.js +18 -0
  12. package/lib/herdr/constants.js.map +1 -1
  13. package/lib/herdr/reporter.d.ts +20 -4
  14. package/lib/herdr/reporter.d.ts.map +1 -1
  15. package/lib/herdr/reporter.js +70 -20
  16. package/lib/herdr/reporter.js.map +1 -1
  17. package/lib/herdr/state.d.ts +10 -0
  18. package/lib/herdr/state.d.ts.map +1 -1
  19. package/lib/herdr/state.js +21 -4
  20. package/lib/herdr/state.js.map +1 -1
  21. package/lib/index.d.ts.map +1 -1
  22. package/lib/index.js +5 -0
  23. package/lib/index.js.map +1 -1
  24. package/lib/install-skills.d.ts +20 -1
  25. package/lib/install-skills.d.ts.map +1 -1
  26. package/lib/install-skills.js +84 -9
  27. package/lib/install-skills.js.map +1 -1
  28. package/lib/surface/background-work.d.ts +2 -0
  29. package/lib/surface/background-work.d.ts.map +1 -1
  30. package/lib/surface/background-work.js +28 -2
  31. package/lib/surface/background-work.js.map +1 -1
  32. package/lib/surface/commands.d.ts +2 -0
  33. package/lib/surface/commands.d.ts.map +1 -1
  34. package/lib/surface/commands.js +6 -0
  35. package/lib/surface/commands.js.map +1 -1
  36. package/lib/surface/modal-input.d.ts +3 -2
  37. package/lib/surface/modal-input.d.ts.map +1 -1
  38. package/lib/surface/modal-input.js +14 -8
  39. package/lib/surface/modal-input.js.map +1 -1
  40. package/lib/surface/session-lifecycle.d.ts.map +1 -1
  41. package/lib/surface/session-lifecycle.js +3 -0
  42. package/lib/surface/session-lifecycle.js.map +1 -1
  43. package/lib/theme-files.d.ts +1 -1
  44. package/lib/theme-files.d.ts.map +1 -1
  45. package/lib/theme-files.js +1 -1
  46. package/lib/theme-files.js.map +1 -1
  47. package/lib/theme-settings.d.ts.map +1 -1
  48. package/lib/theme-settings.js +10 -2
  49. package/lib/theme-settings.js.map +1 -1
  50. package/lib/ui/view/tool-card.d.ts +13 -2
  51. package/lib/ui/view/tool-card.d.ts.map +1 -1
  52. package/lib/ui/view/tool-card.js +19 -3
  53. package/lib/ui/view/tool-card.js.map +1 -1
  54. package/lib/ui/view.d.ts +25 -3
  55. package/lib/ui/view.d.ts.map +1 -1
  56. package/lib/ui/view.js +54 -7
  57. package/lib/ui/view.js.map +1 -1
  58. package/package.json +1 -1
  59. package/themes/violet-orbit.yaml +7 -5
@@ -8,11 +8,23 @@
8
8
  * invisible in the UI. This reads the same two inputs the resolver does - the
9
9
  * owned catalog in the profile patch, and the installed pi-ai provider data -
10
10
  * and names where each number came from: "installed" for the source's own
11
- * entry, "template:<id>" for a clone, "metadata" for what the catalog declares.
11
+ * entry, "template:<id>" for a clone, "route" for the protocol a sourceless
12
+ * route declares once for every model it serves, "metadata" for what the
13
+ * catalog declares.
14
+ *
12
15
  * An entry the catalog spells out completely needs no installed entry at all,
13
- * so a missing harness install must not hide it.
16
+ * so a missing harness install must not hide it. A `filter` route is the
17
+ * exception: its membership is the installed catalog's, so it cannot be read
18
+ * without that install. A declaration the plugin's resolver would refuse is
19
+ * reported as a refusal here too, because a catalog that cannot compose serves
20
+ * nothing.
21
+ *
22
+ * Usage: dump-model-catalog.mjs [--home <dsh home>] [--profile <name>]
23
+ * [--data <pi-ai data dir>] [--json]
14
24
  *
15
- * Usage: dump-model-catalog.mjs [--home <dsh home>] [--profile <name>] [--json]
25
+ * `--data` names the installed provider-data directory to inherit from, which
26
+ * is how a reading is checked where no harness is installed - a `filter` route
27
+ * and every template clone need one.
16
28
  */
17
29
  import { execFileSync } from 'node:child_process'
18
30
  import { readFileSync, realpathSync } from 'node:fs'
@@ -23,9 +35,15 @@ import { fileURLToPath } from 'node:url'
23
35
  const LEVELS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']
24
36
  /** Fields a catalog entry may inherit, and the layer each value came from. */
25
37
  const INHERITED_FIELDS = ['contextWindow', 'maxTokens', 'cost', 'input', 'reasoning', 'thinkingLevelMap', 'api']
38
+ /** What a model with no installed sibling and no template must state itself. */
39
+ const REQUIRED_METADATA = ['api', 'reasoning', 'input', 'cost', 'contextWindow', 'maxTokens']
40
+ const COST_FIELDS = ['input', 'output', 'cacheRead', 'cacheWrite']
26
41
  const INSTALLED = 'installed'
27
42
  const METADATA = 'metadata'
43
+ const ROUTE = 'route'
28
44
  const ABSENT = 'none'
45
+ /** The only wildcard a `filter` pattern carries; every other character is itself. */
46
+ const WILDCARD = '*'
29
47
 
30
48
  /** The levels pi-ai offers: a null mapping removes one, and xhigh/max need one. */
31
49
  export function supportedLevels(levelMap) {
@@ -38,12 +56,13 @@ export function supportedLevels(levelMap) {
38
56
  }
39
57
 
40
58
  function parseArgs(argv) {
41
- const options = { home: process.env.DSH_HOME ?? join(homedir(), '.dsh'), profile: 'tui', json: false }
59
+ const options = { home: process.env.DSH_HOME ?? join(homedir(), '.dsh'), profile: 'tui', data: undefined, json: false }
42
60
  for (let index = 0; index < argv.length; index += 1) {
43
61
  const flag = argv[index]
44
62
  if (flag === '--json') options.json = true
45
63
  else if (flag === '--home') options.home = argv[++index]
46
64
  else if (flag === '--profile') options.profile = argv[++index]
65
+ else if (flag === '--data') options.data = argv[++index]
47
66
  else throw new Error('unknown argument ' + flag)
48
67
  }
49
68
  return options
@@ -74,7 +93,7 @@ export function catalogConfig(patch) {
74
93
  }
75
94
 
76
95
  export function providerData(directory, source) {
77
- if (directory === undefined) return undefined
96
+ if (directory === undefined || source === undefined) return undefined
78
97
  try {
79
98
  return JSON.parse(readFileSync(join(directory, source + '.json'), 'utf8'))
80
99
  } catch {
@@ -82,6 +101,28 @@ export function providerData(directory, source) {
82
101
  }
83
102
  }
84
103
 
104
+ /** Installed models in the order the source publishes them, one api map at a time. */
105
+ function installedModels(data) {
106
+ if (data === undefined) return []
107
+ return Object.entries(data).flatMap(([api, models]) => Object.entries(models)
108
+ .map(([id, model]) => ({ ...model, id, api: model.api ?? api })))
109
+ }
110
+
111
+ /** Mirror the resolver's pattern rule so a filter reads the same here and there. */
112
+ function patternToRegExp(pattern) {
113
+ const escaped = pattern.split(WILDCARD).map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
114
+ return new RegExp('^' + escaped.join('.*') + '$')
115
+ }
116
+
117
+ /** A filter keeps installed facts and order, then drops what exclude names. */
118
+ export function expandFilter(data, filter) {
119
+ const include = filter?.include === undefined ? undefined : filter.include.map(patternToRegExp)
120
+ const exclude = filter?.exclude === undefined ? [] : filter.exclude.map(patternToRegExp)
121
+ return installedModels(data)
122
+ .filter(model => (include === undefined || include.some(pattern => pattern.test(model.id)))
123
+ && !exclude.some(pattern => pattern.test(model.id)))
124
+ }
125
+
85
126
  /** Look one id up across a provider's api maps; an api in the spec disambiguates. */
86
127
  function lookup(data, id, api) {
87
128
  if (data === undefined) return undefined
@@ -91,8 +132,13 @@ function lookup(data, id, api) {
91
132
  return undefined
92
133
  }
93
134
 
135
+ function costOf(cost) {
136
+ if (cost === undefined) return undefined
137
+ return '$' + COST_FIELDS.map(field => cost[field]).join('/') + ' per 1M'
138
+ }
139
+
94
140
  /** Resolve one catalog entry against the installed data it may inherit from. */
95
- export function resolve(spec, data) {
141
+ export function resolve(spec, data, routeApi) {
96
142
  const metadata = spec.metadata ?? {}
97
143
  const declared = Object.keys(metadata).length > 0
98
144
  const cloneOf = spec.template ?? spec.id
@@ -101,37 +147,88 @@ export function resolve(spec, data) {
101
147
  return { error: 'no source entry for ' + cloneOf + '; declare a template or metadata' }
102
148
  }
103
149
  const merged = { ...base, ...metadata, id: spec.id, name: spec.name ?? base?.name ?? spec.id }
104
- merged.maxTokens = metadata.maxTokens ?? spec.defaultMaxTokens ?? base?.maxTokens
150
+ // A route that names no source states its protocol once, for every model.
151
+ if (merged.api === undefined && routeApi !== undefined) merged.api = routeApi
152
+ // Capacity and the request default are different numbers, and the resolver
153
+ // caps one by the other: folding them would hide the mistake it refuses.
154
+ const capacity = metadata.maxTokens ?? base?.maxTokens
155
+ const missing = base === undefined
156
+ ? REQUIRED_METADATA.filter(field => field === 'api' ? merged.api === undefined : metadata[field] === undefined)
157
+ : []
158
+ if (missing.length > 0) return { error: 'unknown model requires complete metadata: missing ' + missing.join(', ') }
159
+ if (spec.defaultMaxTokens !== undefined && capacity !== undefined && spec.defaultMaxTokens > capacity) {
160
+ return { error: 'defaultMaxTokens ' + spec.defaultMaxTokens + ' exceeds model maxTokens ' + capacity }
161
+ }
105
162
  const origins = {}
106
163
  for (const field of INHERITED_FIELDS) {
107
- const declaredValue = field === 'maxTokens' ? metadata.maxTokens ?? spec.defaultMaxTokens : metadata[field]
108
- if (declaredValue !== undefined) origins[field] = METADATA
164
+ if (metadata[field] !== undefined) origins[field] = METADATA
165
+ else if (field === 'api' && base === undefined && routeApi !== undefined) origins[field] = ROUTE
109
166
  else if (base === undefined) origins[field] = ABSENT
110
167
  else origins[field] = spec.template === undefined ? INSTALLED : 'template:' + spec.template
111
168
  }
112
- return { model: merged, origins, levels: supportedLevels(merged.thinkingLevelMap) }
169
+ return {
170
+ model: { ...merged, maxTokens: capacity },
171
+ origins,
172
+ levels: supportedLevels(merged.thinkingLevelMap),
173
+ ...(spec.defaultMaxTokens === undefined ? {} : { requestMax: spec.defaultMaxTokens }),
174
+ ...(spec.aliases === undefined ? {} : { aliases: spec.aliases.join(',') }),
175
+ ...(metadata.cost?.tiers === undefined ? {} : {
176
+ tiers: metadata.cost.tiers.map(tier => 'above ' + tier.inputTokensAbove + ': ' + costOf(tier)).join('; '),
177
+ }),
178
+ }
113
179
  }
114
180
 
115
181
  function rowsOf(catalog, directory) {
116
182
  const rows = []
117
183
  for (const provider of catalog.providers ?? []) {
118
184
  const data = providerData(directory, provider.source)
185
+ const hasModels = 'models' in provider
186
+ const hasFilter = 'filter' in provider
187
+ // The resolver refuses both and neither; saying so here beats serving half.
188
+ if (hasModels === hasFilter) {
189
+ rows.push({ route: provider.id, error: 'declare exactly one of models or filter' })
190
+ continue
191
+ }
192
+ if (hasFilter) {
193
+ if (data === undefined) {
194
+ rows.push({
195
+ route: provider.id,
196
+ error: 'filter expands the installed catalog of source "' + provider.source + '"; no harness install found',
197
+ })
198
+ continue
199
+ }
200
+ for (const model of expandFilter(data, provider.filter)) {
201
+ rows.push({
202
+ route: provider.id + '/' + model.id,
203
+ name: model.name ?? model.id,
204
+ api: model.api,
205
+ contextWindow: model.contextWindow,
206
+ maxTokens: model.maxTokens,
207
+ cost: costOf(model.cost),
208
+ levels: supportedLevels(model.thinkingLevelMap).join(','),
209
+ origins: 'filter:' + (provider.filter.include ?? [WILDCARD]).join(',') + ' all installed',
210
+ })
211
+ }
212
+ continue
213
+ }
119
214
  for (const spec of provider.models ?? []) {
120
- const result = resolve(spec, data)
215
+ const result = resolve(spec, data, provider.api)
121
216
  const route = provider.id + '/' + spec.id
122
217
  if (result.error !== undefined) {
123
218
  rows.push({ route, error: result.error })
124
219
  continue
125
220
  }
126
- const cost = result.model.cost ?? {}
127
221
  rows.push({
128
222
  route,
129
223
  name: result.model.name,
130
224
  api: result.model.api,
131
225
  contextWindow: result.model.contextWindow,
132
226
  maxTokens: result.model.maxTokens,
133
- cost: '$' + [cost.input, cost.output, cost.cacheRead, cost.cacheWrite].join('/') + ' per 1M',
227
+ cost: costOf(result.model.cost),
134
228
  levels: result.levels.join(','),
229
+ ...(result.requestMax === undefined ? {} : { requestMax: result.requestMax }),
230
+ ...(result.aliases === undefined ? {} : { aliases: result.aliases }),
231
+ ...(result.tiers === undefined ? {} : { tiers: result.tiers }),
135
232
  origins: INHERITED_FIELDS
136
233
  .map(field => [field, result.origins[field]])
137
234
  .filter(([, origin]) => origin !== INSTALLED)
@@ -143,6 +240,39 @@ function rowsOf(catalog, directory) {
143
240
  return rows
144
241
  }
145
242
 
243
+ /**
244
+ * The default is part of the catalog, not a comment beside it: the resolver
245
+ * refuses a selection nothing serves, so a reading that skipped it would call a
246
+ * broken catalog readable.
247
+ */
248
+ export function checkDefault(catalog, rows) {
249
+ const served = rows.filter(row => row.error === undefined)
250
+ const selection = catalog.default ?? null
251
+ if (served.length === 0) {
252
+ return selection === null ? [] : [{ route: 'default', error: 'an empty catalog requires default null' }]
253
+ }
254
+ if (selection === null || typeof selection !== 'object') {
255
+ return [{ route: 'default', error: 'a served catalog requires a default selection' }]
256
+ }
257
+ const alias = new Map()
258
+ for (const provider of catalog.providers ?? []) {
259
+ for (const model of provider.models ?? []) {
260
+ for (const name of [model.id, ...(model.aliases ?? [])]) alias.set(provider.id + '/' + name, model.id)
261
+ }
262
+ }
263
+ const route = selection.provider + '/' + selection.model
264
+ const canonical = alias.get(route)
265
+ const row = served.find(candidate => candidate.route === selection.provider + '/' + (canonical ?? selection.model))
266
+ if (row === undefined) {
267
+ return [{ route: 'default', error: 'provider/model is outside the managed selection: ' + route }]
268
+ }
269
+ const effort = selection.reasoningEffort
270
+ if (effort !== undefined && !String(row.levels).split(',').includes(effort)) {
271
+ return [{ route: 'default', error: 'effort is not supported by the selected model: ' + effort }]
272
+ }
273
+ return []
274
+ }
275
+
146
276
  function main() {
147
277
  const options = parseArgs(process.argv.slice(2))
148
278
  const patch = join(options.home, 'profiles', options.profile, 'cordis.patch.yml')
@@ -152,11 +282,12 @@ function main() {
152
282
  + 'this profile wires models another way; see references/model-wiring.md\n')
153
283
  process.exit(1)
154
284
  }
155
- const directory = dataDirectory()
285
+ const directory = options.data ?? dataDirectory()
156
286
  if (directory === undefined) {
157
287
  process.stderr.write('no harness install found; entries that inherit from it cannot be checked\n')
158
288
  }
159
- const rows = rowsOf(catalog, directory)
289
+ const served = rowsOf(catalog, directory)
290
+ const rows = [...served, ...checkDefault(catalog, served)]
160
291
  const unresolved = rows.filter(row => row.error !== undefined).length
161
292
  if (options.json) {
162
293
  process.stdout.write(JSON.stringify({ default: catalog.default ?? null, rows }, null, 2) + '\n')
@@ -167,7 +298,12 @@ function main() {
167
298
  continue
168
299
  }
169
300
  process.stdout.write(row.route + '\n ' + row.name + ' | ' + row.api + ' | ctx ' + row.contextWindow
170
- + ' | max ' + row.maxTokens + ' | ' + row.cost + ' | efforts ' + row.levels + '\n inherited: ' + row.origins + '\n')
301
+ + ' | max ' + row.maxTokens
302
+ + (row.requestMax === undefined ? '' : ' | req ' + row.requestMax)
303
+ + ' | ' + row.cost
304
+ + (row.tiers === undefined ? '' : ' | tiers ' + row.tiers)
305
+ + ' | efforts ' + row.levels
306
+ + (row.aliases === undefined ? '' : ' | aliases ' + row.aliases) + '\n inherited: ' + row.origins + '\n')
171
307
  }
172
308
  process.stdout.write('default: ' + JSON.stringify(catalog.default ?? null) + '\n')
173
309
  }
package/README.md CHANGED
@@ -57,6 +57,20 @@ The command stages the new copy before replacement and restores the old
57
57
  copy if replacement fails. If cleanup fails after replacement, the new copy
58
58
  stays installed and the command reports the old backup path.
59
59
 
60
+ A started session compares every installed copy with the skills this build
61
+ ships and prints one line when they differ, because an agent loading a stale
62
+ skill is told the old wiring:
63
+
64
+ ```text
65
+ bundled skills changed since they were installed: dsh-tui-update-models · run dsh --profile tui install-skills --update
66
+ ```
67
+
68
+ The comparison reads content only, over the files this package ships: a
69
+ helper's execute bit is the installer's own doing, and a note kept beside a
70
+ skill stays unremarked. A skill that was never installed is not drift — a first
71
+ install is the prompt above — and a run that never opens the screen, like
72
+ `list-models`, prints nothing.
73
+
60
74
  ### Confirm the plugin mounted
61
75
 
62
76
  The profile records its layers in `$DSH_HOME/profiles/tui/package.json` (`~/.dsh` by default). `@sagmans/dsh-tui` must appear in `dsh.profile.bundles`:
@@ -167,7 +181,7 @@ force, and the `keys:` section moves any of them — see [Keys](#keys).
167
181
  | Ctrl+C | take back one thing at a time: the draft in the bar, the prompts waiting in the agent's inbox, the running turn, or a child's conversation; with a picker, an approval, a question, or the transcript search open it closes that instead. With nothing left to cancel it does nothing — it never leaves |
168
182
  | Ctrl+D | leave and print the resume command, when the bar holds no text and nothing is open; a running turn is cancelled first |
169
183
  | Ctrl+O | open every tool card: its header plus every retained row. Folded, a card is one line, and a shell card keeps its command plus the last 20 rows of output with a hint naming what it dropped |
170
- | Ctrl+Y | show or hide the calls a PTC program dispatched: one two-space-indented row per call under its `run_code` card, named and argued from the tool's own header and cut at the screen edge; clicking one row opens that call in full — the change it declared, then what it produced — for every tool, a failed call included; shown by default |
184
+ | Ctrl+Y | show or hide the calls a PTC program dispatched: one two-space-indented row per call under its `run_code` card, named and argued from the tool's own header and cut at the screen edge; clicking the card's own header does the same for that card alone, and one level only — the program's own rows stay under `Ctrl+O`; clicking one call's row opens that call in full — the change it declared, then what it produced — for every tool, a failed call included; hidden by default |
171
185
  | Shift+Tab | expand or fold every thought behind the answers: folded, the row names itself, its token count, and the key; opened, it adds the thought, laid out as markdown; a click decides for one thought instead |
172
186
  | Ctrl+T | pick the reasoning effort for the next step |
173
187
  | Ctrl+R | reverse-search recorded prompts: the list opens filtered by whatever is in the bar, `enter` puts one back, `esc` keeps the draft |
@@ -370,8 +384,8 @@ code. Released hosts with section APIs store preferences in
370
384
 
371
385
  ```yaml
372
386
  dsh-tui:
373
- theme: violet-orbit # restyle the whole surface by name (default: deepseek-blue)
374
- subcalls: collapsed # fold the calls a PTC program dispatched (default inline)
387
+ theme: deepseek-blue # restyle the whole surface by name (default: violet-orbit)
388
+ subcalls: inline # draw the calls a PTC program dispatched (default collapsed)
375
389
  mermaid: streaming # draw a reply's mermaid fences: off, final, or streaming (default streaming)
376
390
  tools:
377
391
  default: { collapsed: true, output: hidden } # how every tool's card starts
@@ -462,11 +476,12 @@ keymap on the next press, and `/theme` shows each element's effective value and
462
476
  whether it came from an override, the palette, or the default.
463
477
 
464
478
 
465
- The section is not only shades. By default every session draws one row per call
466
- a PTC program dispatched under its card, and `subcalls: collapsed` starts with
467
- the card alone instead. `Ctrl+Y` toggles the same choice for the current
468
- session, and an edit to the document re-seeds it. An unknown key or value is
469
- refused with a notice naming it, so a typo cannot quietly do nothing.
479
+ The section is not only shades. By default a PTC program's card arrives alone,
480
+ and `subcalls: inline` draws one row per call it dispatched under that card
481
+ instead — or one click on the card's own header, for that card alone.
482
+ `Ctrl+Y` toggles the same choice for the current session, and an edit to the
483
+ document re-seeds it. An unknown key or value is refused with a notice naming
484
+ it, so a typo cannot quietly do nothing.
470
485
 
471
486
  The `tools` block decides how each tool's cards draw. `collapsed` starts a
472
487
  tool folded to one header row (default `true`), and `output` is `hidden`
@@ -480,8 +495,11 @@ profile mounts. Clicking a card opens or folds that one message, and a dispatche
480
495
  call's row opens on the same click to what the tool itself drew for it — an
481
496
  edit's diff in the diff colours, a read's numbered lines, a command and its
482
497
  output — followed by the outcome it produced; a call that failed opens to the
483
- reason it reported instead of rows for work that never happened. `Ctrl+O` still
484
- decides for every message nobody clicked.
498
+ reason it reported instead of rows for work that never happened. A program's
499
+ card opens one level at a time: its own row draws the calls, and the rows below
500
+ them — what the program returned — are the card's, so a click on each answers
501
+ for what it drew. `Ctrl+O` still decides for every message nobody clicked, and
502
+ `Ctrl+Y` for every program whose own header nobody clicked.
485
503
 
486
504
  The `history` block tunes the prompt history. `enabled: false` stops recording
487
505
  and offering it; `ghost: false` keeps reverse search but stops the dimmed
@@ -520,9 +538,9 @@ leaving a gap, and `NO_COLOR` draws the fence as plain text. `/export` and the
520
538
  session file still keep the fence exactly as the model wrote it.
521
539
 
522
540
  A theme restyles the whole surface by name, and a theme is a file. The package
523
- ships two: `deepseek-blue`, the table written out in full in the colours the
524
- project answers to, and `violet-orbit`, a port of pi's theme of that name — its
525
- palette, plus the elements it draws its own way. `deepseek-blue` is also what a
541
+ ships two: `violet-orbit`, a port of pi's theme of that name — its palette, plus
542
+ the elements it draws its own way — and `deepseek-blue`, the table written out
543
+ in full in the colours the project answers to. `violet-orbit` is also what a
526
544
  document naming no theme draws, so the default look is a file you can read, list,
527
545
  and copy rather than a table compiled in. Your own themes live in
528
546
  `$DSH_HOME/themes/`, which the surface creates at start-up and watches, so saving
@@ -712,7 +730,7 @@ The fold is durable-only: the live stream decorates the row that is still being
712
730
 
713
731
  Tool cards are folded by default: a card draws one header row — the tool, its argument clipped to the configured budget, and the facts the result measured — so a long read, diff, or search cannot bury the conversation. A call that has not answered yet names itself in the running colour, `tool.running.title`, and ends that row with the whole seconds it has been waiting, in `tool.running.elapsed`, once it has waited one, so a reader can tell the call they are watching from the one below it that already finished; both give way to the measured facts the moment the result lands. A call that failed names itself in the failed colour, `tool.failed.title` — including a shell whose command exited non-zero or died on a signal, which is a failure whether or not the tool that ran it said so. A shell card's row also carries the exit status and the count of output rows waiting behind the fold, because its output is the answer the reader asked for and a fold that left no trace of it would read as a call that produced nothing. Clicking a card opens or folds that one message; `Ctrl+O` opens or folds every card at once, and `tools:` in the [settings](#settings) decides how each tool starts and whether a fold hides its rows or keeps a `tail` of them.
714
732
 
715
- A PTC card is the one card with children: every call the `run_code` program dispatched hangs off the card that made it, and each draws under the header as the tool's own name and argument, on one row cut at the screen edge whether the card itself is open or folded — a program's work must stay legible without opening its card. Each of those rows names its own call in the colour of what that call is doing — `tool.subcall.running` while the program is waiting on it, `tool.failed.title` when it failed, and `tool.subcall.title` once it is back — and a settled row keeps the one line the tool itself drew about its outcome, in `tool.terminal.status` where that tool declares one. A shell call therefore reads `bash pnpm test · exit 0` when it worked and the same row in red, with `exit 1`, when it did not, so a program's work reads row by row without opening the card. The program's own row is the one card that shows no mark: its timer is what says it is still running, and it is also what the card keeps when the program answers — the total it ran for, drawn in `tool.elapsed.done`, dimmed and italic, because the work it measured is over. Clicking one of those rows opens that call's argument in full and leaves its neighbours and the card as they were; a shell call also brings back the rows it printed, because the program's return value is all the card itself keeps. `Ctrl+Y` hides or shows them all, and `subcalls: collapsed` starts every session with them hidden; see [Settings](#settings).
733
+ A PTC card is the one card with children: every call the `run_code` program dispatched hangs off the card that made it, and once shown, each draws under the header as the tool's own name and argument, on one row cut at the screen edge whether the card itself is open or folded — a program's work must stay legible without opening its card. Those rows start folded, because a program can dispatch hundreds of calls and what a reader came for is the answer they produced: one click on the card's own header draws them for that card and for that card alone, `Ctrl+Y` draws them for every card at once, and `subcalls:` decides what a session starts with. Nothing else arrives with that click: the program's own rows are the level below, and `Ctrl+O` is what opens them. Each of those rows names its own call in the colour of what that call is doing — `tool.subcall.running` while the program is waiting on it, `tool.failed.title` when it failed, and `tool.subcall.title` once it is back — and a settled row keeps the one line the tool itself drew about its outcome, in `tool.terminal.status` where that tool declares one. A shell call therefore reads `bash pnpm test · exit 0` when it worked and the same row in red, with `exit 1`, when it did not, so a program's work reads row by row without opening the card. The program's own row is the one card that shows no mark: its timer is what says it is still running, and it is also what the card keeps when the program answers — the total it ran for, drawn in `tool.elapsed.done`, dimmed and italic, because the work it measured is over. Clicking one of those rows opens that call's argument in full and leaves its neighbours and the card as they were; a shell call also brings back the rows it printed, because the program's return value is all the card itself keeps. `Ctrl+Y` hides or shows them all, and `subcalls: collapsed`, the shipped default, starts every session with them hidden; see [Settings](#settings).
716
734
 
717
735
  A card's header names the tool, then the argument the call was made with — a path or a command — in the `tool.args` colour, then the facts the result measured: a read reports its line range, line count, and token size; a file change that carried no prior content to compare against reports its lines and tokens; one that did reports added, changed, and removed lines as `+n ~n -n` in green, yellow, and red. Each stat is its own token, so any of them can be recoloured or hidden independently, and so are the elements a call in flight is drawn with — hiding `tool.running.elapsed` leaves the name in its running colour, hiding `tool.running.title` leaves the seconds counting, hiding `tool.elapsed.done` takes the total off a program's settled row, and a dispatched row is toned the same way per state with `tool.subcall.running` and `tool.subcall.title`. A state is only how a name is painted, so hiding one of those colours leaves the name in the colour a call with no state is read in rather than taking the name away.
718
736
 
@@ -751,15 +769,29 @@ The list the dock and `/todo` draw follows the same lifetime every other surface
751
769
  |---|---|
752
770
  | the screen is taken, before any session opens | `idle`, claiming the pane's agent row |
753
771
  | the agent's driver starts, including a run of turns chained through pending work | `working` |
754
- | an approval, a question, or a picker takes the keyboard | `blocked`, with that card's title sent along |
755
- | the decision settles | `working` if the driver is running, otherwise `idle` |
756
- | the agent's driver stops with nothing pending | `idle` |
772
+ | a subagent or background job remains live after the driver stops | `working` until the last one settles |
773
+ | an approval or a question takes the keyboard | `blocked`, with that card's title sent along, and set as the `blocked` display label |
774
+ | the decision settles | `working` if the driver or background work is running, otherwise `idle` |
775
+ | the agent's driver stops with no live subagent or job | `idle` |
757
776
  | a session opens, resumes, forks, or is switched to | its id and reason, plus the `dsh_session` / `dsh_cwd` pane tokens |
758
777
  | exit, signal, or boot failure | `herdr pane release-agent`, so no row is left waiting on a process that is gone |
759
778
 
760
- A wait outranks a running driver: an agent waiting on a human is not making progress, and the wait is the only thing worth acting on from a wall of panes. The pane reports the agent's driver rather than each turn: the harness chains turns through a pending inbox inside one driver run, and reporting each turn's end would read as done between two turns of an agent that is still working. Reports are sequenced per source, so a delivery that arrives late cannot undo the state the surface already moved past, and a state Herdr is already showing is not sent again. A report is only counted as made when Herdr acknowledges it: one that failed is tried again — soon after, then with a growing wait — and a session identity Herdr never confirmed travels with the next report of any kind. The retry cannot wait for another state change, because the pane may have nothing left to say: a driver that stopped while the socket was down produces no further event. States still waiting to be sent are collapsed into the newest one, so a socket that was down for a minute is told where the pane is rather than where it has been. The release carries the next number in that same sequence for the same reason: Herdr reads one that cannot beat the pane's last report as stale, and a stale release leaves the row waiting on a process that is gone. It also stops reporting first — a claim landing after the release would take the row back for a process that is leaving — and the report already on the wire is waited for before the row goes back, because Herdr ignores the release of a pane nothing has claimed yet and that late report would then claim it. What is still waiting behind it is dropped rather than sent.
779
+ A picker is deliberately absent from that table. Herdr answers a transition into `blocked` with a needs-attention notification and its sound, and 0.9.1 plays it for the focused pane of the active tab as well as for a background one, so a menu the reader opened themselves would ring for their own navigation — once per menu, on the model picker and the reasoning picker behind it — and the row would read as an agent stuck on a decision it never asked for. A gate is the opposite case: the agent asked, and may have asked somebody who walked away.
780
+
781
+ A wait outranks running work: an agent waiting on a human is not making progress, and the wait is the only thing worth acting on from a wall of panes. The pane follows the agent's driver and the live subagents and jobs it owns. The harness chains turns through a pending inbox inside one driver run, and reporting each turn's end would read as done between two turns of an agent that is still working. A parent driver can also stop while a delegated child or job continues, so its idle transition alone does not make the pane done. The job registry announces settlement before its completion notice wakes the parent, so the pane checks for idle after that handoff instead of briefly announcing done in the middle. Reports are sequenced per source, so a delivery that arrives late cannot undo the state the surface already moved past, and a state Herdr is already showing is not sent again. A report is only counted as made when Herdr acknowledges it: one that failed is tried again — soon after, then with a growing wait — and a session identity Herdr never confirmed travels with the next report of any kind. The retry cannot wait for another state change, because the pane may have nothing left to say: a driver that stopped while the socket was down produces no further event. States still waiting to be sent are collapsed into the newest one, so a socket that was down for a minute is told where the pane is rather than where it has been. The release carries the next number in that same sequence for the same reason: Herdr reads one that cannot beat the pane's last report as stale, and a stale release leaves the row waiting on a process that is gone. It also stops reporting first — a claim landing after the release would take the row back for a process that is leaving — and the report already on the wire is waited for before the row goes back, because Herdr ignores the release of a pane nothing has claimed yet and that late report would then claim it. What is still waiting behind it is dropped rather than sent.
782
+
783
+ Herdr persists a session reference only for its own built-in integrations, so this pane's session identity travels as metadata tokens instead: a script or a companion plugin reads them back with `herdr pane get <id>` and resumes that exact conversation with `dsh --profile tui --resume=<id>`. Herdr holds a token value up to 80 characters and shortens anything longer, so a session id or directory that cannot be sent whole has its token cleared instead: a shortened path would read as a different directory, and a pane must not claim one. What Herdr cannot do is identify the process itself — its detection table and its screen rules both name built-in agents only — so a pane that has not reported yet reads as an ordinary pane, and is not yet a target: `herdr agent wait` on it fails with `agent_not_found` until the first report lands. Herdr 0.9.1 keeps the title that accompanies a `blocked` state without drawing it anywhere, so the same title is sent again as that state's display label — the one Herdr's sidebar renders through its `state_text` token. The complete default agent rows do not include it:
784
+
785
+ ```toml
786
+ [ui.sidebar.agents]
787
+ rows = [
788
+ ["state_icon", "machine", "workspace", "tab"],
789
+ ["state_text"],
790
+ ["agent"],
791
+ ]
792
+ ```
761
793
 
762
- Herdr persists a session reference only for its own built-in integrations, so this pane's session identity travels as metadata tokens instead: a script or a companion plugin reads them back with `herdr pane get <id>` and resumes that exact conversation with `dsh --profile tui --resume=<id>`. Herdr holds a token value up to 80 characters and shortens anything longer, so a session id or directory that cannot be sent whole has its token cleared instead: a shortened path would read as a different directory, and a pane must not claim one. What Herdr cannot do is identify the process itself — its detection table and its screen rules both name built-in agents only — so a pane that has not reported yet reads as an ordinary pane, and is not yet a target: `herdr agent wait` on it fails with `agent_not_found` until the first report lands. Herdr 0.9.1 also keeps the title that accompanies a `blocked` state without showing it anywhere, so a reader sees the state and reads the card on screen.
794
+ With that row present, a pane waiting on a decision names the tool that asked instead of showing a colour alone. A label longer than the 80 characters Herdr holds whole is cut here rather than server-side, so the ellipsis lands where this surface put it; the message that rides the state report keeps its own, longer bound.
763
795
 
764
796
  ## Development
765
797
 
@@ -776,6 +808,7 @@ pnpm run build
776
808
  node tools/pty-drive.mjs --prompt 'Reply with exactly: pong'
777
809
  node tools/pty-drive.mjs --prompt 'Run: echo hi' --approve 20 # answer the approval gate
778
810
  node tools/pty-drive.mjs --home /tmp/scratch-home --seconds 20 # no credentials: proves failures are visible
811
+ node tools/pty-drive.mjs --prompt 'Run: echo hi' --click 20:12 # press the left button at row 12
779
812
  ```
780
813
 
781
814
  Keep verification off your real home: install the profile into a throwaway one and copy only the credentials it needs.
@@ -805,11 +838,11 @@ The automated checks drive a real PTY, but they run on this machine's terminal.
805
838
  | `NO_COLOR=1 dsh --profile tui` | no styling anywhere, layout unchanged |
806
839
  | `dsh --profile tui --no-bell` | a turn that runs for minutes still ends silently |
807
840
  | `dsh --profile tui --preset ptc`, then a turn | the status line names `ptc`, and the agent reaches its tools through one TypeScript program rather than one shell call at a time |
808
- | a PTC turn | one row per dispatched call draws two spaces indented under the `run_code` header without opening it |
841
+ | a PTC turn | the `run_code` card arrives alone, whatever the program dispatched; `ctrl+y` draws one row per call two spaces indented under it without opening it, and a click on the card's own header does the same for that card — and for that card alone, one level, with the program's own rows still behind `ctrl+o` |
809
842
  | that turn, then a click on one of those rows | that call unfolds in full at the same indent: its argument, then what the tool itself drew — an edit's diff in the diff colours, a read's lines, a shell's output — and its neighbours and the card stay as they were |
810
843
  | a PTC turn in which a dispatched call failed, then a click on that red row | the row opens to the reason the call reported, and a click on those rows folds it back |
811
- | that same turn, then `ctrl+y` | the rows fold away; `ctrl+y` again draws them back |
812
- | `dsh-tui: { subcalls: collapsed }` in `$DSH_HOME/settings.yaml`, then a PTC turn | the card arrives alone, and editing the document to `inline` draws the one-line calls in a running session |
844
+ | that same turn, then `ctrl+y` | the rows draw under the folded card; `ctrl+y` again folds them away, and one click on the card's own header does the same for that card alone |
845
+ | `dsh-tui: { subcalls: inline }` in `$DSH_HOME/settings.yaml`, then a PTC turn | the one-line calls draw under the card; deleting the key folds them away |
813
846
  | a thought, folded | a click on the row opens the thought under its summary; a click on the body folds it back, and the other thoughts keep their own state |
814
847
  | a bash card, then a click on it | the row opens to its command, its retained output, and its exit status; a click folds it back to one row |
815
848
  | a bash command that exits non-zero | the same row as any other failure: the tool's name in the failed colour, with the `exit 1` it ended on |
@@ -29,6 +29,14 @@ export interface HerdrClient {
29
29
  reportState(report: StateReport): Promise<boolean>;
30
30
  reportSession(report: SessionReport): Promise<boolean>;
31
31
  reportMetadata(tokens: Readonly<Record<string, string | undefined>>): Promise<boolean>;
32
+ /**
33
+ * What Herdr writes for a blocked row, or the request to forget that label.
34
+ *
35
+ * A separate channel from the state report because Herdr keeps a wait's
36
+ * message without rendering it: the display label is the one its sidebar
37
+ * reads, so naming the decision the reader owes needs both.
38
+ */
39
+ reportStateLabel(label: string | undefined): Promise<boolean>;
32
40
  /** Stop accepting reports and drop the ones still waiting. */
33
41
  stop(): void;
34
42
  /** Wait until the transport has finished everything it took on. */
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/herdr/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAYL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;AAE3E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACtD,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACtF,8DAA8D;IAC9D,IAAI,IAAI,IAAI,CAAA;IACZ,mEAAmE;IACnE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAsBD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,gBAA8B,EAAE,OAAO,GAAE,kBAAuB,GAAG,WAAW,CA4GpH;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAMlH;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/herdr/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAaL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;AAE3E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACtD,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACtF;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7D,8DAA8D;IAC9D,IAAI,IAAI,IAAI,CAAA;IACZ,mEAAmE;IACnE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAsBD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,gBAA8B,EAAE,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAwHpH;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAMlH;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD"}
@@ -7,7 +7,7 @@
7
7
  * off stdout and stderr — the alternate screen owns both.
8
8
  */
9
9
  import { createConnection } from 'node:net';
10
- import { DEFAULT_ATTEMPTS, DEFAULT_TIMEOUT_MS, HERDR_AGENT, HERDR_ENV_FLAG, HERDR_ENV_VAR, HERDR_PANE_ID_VAR, HERDR_SOCKET_PATH_VAR, HERDR_SOURCE, MAX_METADATA_VALUE_CHARS, MAX_RESPONSE_BYTES, RESPONSE_DELIMITER, } from "./constants.js";
10
+ import { DEFAULT_ATTEMPTS, DEFAULT_TIMEOUT_MS, HERDR_AGENT, HERDR_ENV_FLAG, HERDR_ENV_VAR, HERDR_PANE_ID_VAR, HERDR_SOCKET_PATH_VAR, HERDR_SOURCE, HERDR_STATES, MAX_METADATA_VALUE_CHARS, MAX_RESPONSE_BYTES, RESPONSE_DELIMITER, } from "./constants.js";
11
11
  /**
12
12
  * Create the client for one pane.
13
13
  *
@@ -99,6 +99,18 @@ export function createHerdrClient(env = process.env, options = {}) {
99
99
  tokens: acceptedTokens(tokens),
100
100
  }, false);
101
101
  },
102
+ reportStateLabel(label) {
103
+ // Not coalescing on purpose: a coalescing entry supersedes every coalescing
104
+ // one already queued, so a label riding that channel would silently drop a
105
+ // state report still waiting to be sent. The label is display-only and the
106
+ // queue is serial, so arrival order is all the ordering it needs.
107
+ return enqueue('pane.report_metadata', {
108
+ applies_to_source: HERDR_SOURCE,
109
+ ...(label === undefined
110
+ ? { clear_state_labels: true }
111
+ : { state_labels: { [HERDR_STATES.blocked]: label } }),
112
+ }, false);
113
+ },
102
114
  stop() {
103
115
  // Nothing still waiting is sent once the pane stops being an agent: Herdr
104
116
  // ignores the release of a pane nothing has claimed, so a report that
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/herdr/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/herdr/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,GAGnB,MAAM,gBAAgB,CAAA;AA8DvB;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAwB,OAAO,CAAC,GAAG,EAAE,UAA8B,EAAE;IACrG,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAA;IACrC,MAAM,UAAU,GAAG,GAAG,CAAC,qBAAqB,CAAC,CAAA;IAC7C,2EAA2E;IAC3E,wDAAwD;IACxD,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,cAAc,IAAI,MAAM,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,CAAA;IACzG,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,gBAAgB,CAAC,CAAA;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC,CAAA;IACtE,IAAI,aAAa,GAAG,CAAC,CAAA;IACrB,IAAI,MAAM,GAAmB,EAAE,CAAA;IAC/B,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,IAAI,OAAO,GAAsB,EAAE,CAAA;IAEnC,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,MAAM,OAAO,GAAG,OAAO,CAAA;QACvB,OAAO,GAAG,EAAE,CAAA;QACZ,KAAK,MAAM,OAAO,IAAI,OAAO;YAAE,OAAO,EAAE,CAAA;IAC1C,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,KAAK,EAAE,OAAoB,EAAoB,EAAE,CAC/D,UAAU,KAAK,SAAS;QACtB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAA;IAE3E,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;QACrC,IAAI,OAAO;YAAE,OAAM;QACnB,OAAO,GAAG,IAAI,CAAA;QACd,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,CAAA;gBAC3B,IAAI,IAAI,KAAK,SAAS;oBAAE,MAAK;gBAC7B,IAAI,CAAC,MAAM,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,OAAO,GAAG,KAAK,CAAA;YACf,IAAI,EAAE,CAAA;QACR,CAAC;IACH,CAAC,CAAA;IAED,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,MAA+B,EAAE,UAAmB,EAAoB,EAAE,CACzG,IAAI,OAAO,CAAU,OAAO,CAAC,EAAE;QAC7B,IAAI,MAAM,IAAI,CAAC,OAAO,IAAI,MAAM,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC3E,OAAO,CAAC,IAAI,CAAC,CAAA;YACb,OAAM;QACR,CAAC;QACD,MAAM,OAAO,GAAgB;YAC3B,EAAE,EAAE,GAAG,YAAY,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,EAAE,aAAa,CAAC,EAAE;YACvE,MAAM;YACN,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE;SACjF,CAAA;QACD,IAAI,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YACzD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YAC3D,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YAClD,uEAAuE;YACvE,mDAAmD;YACnD,KAAK,MAAM,KAAK,IAAI,UAAU;gBAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpD,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;QACrD,KAAK,IAAI,EAAE,CAAA;IACb,CAAC,CAAC,CAAA;IAEJ,OAAO;QACL,OAAO;QACP,WAAW,CAAC,MAAM;YAChB,OAAO,OAAO,CAAC,mBAAmB,EAAE;gBAClC,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpE,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;aAClF,EAAE,IAAI,CAAC,CAAA;QACV,CAAC;QACD,aAAa,CAAC,MAAM;YAClB,OAAO,OAAO,CAAC,2BAA2B,EAAE;gBAC1C,gBAAgB,EAAE,MAAM,CAAC,SAAS;gBAClC,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,oBAAoB,EAAE,MAAM,CAAC,MAAM;aACpC,EAAE,KAAK,CAAC,CAAA;QACX,CAAC;QACD,cAAc,CAAC,MAAM;YACnB,OAAO,OAAO,CAAC,sBAAsB,EAAE;gBACrC,iBAAiB,EAAE,YAAY;gBAC/B,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC;aAC/B,EAAE,KAAK,CAAC,CAAA;QACX,CAAC;QACD,gBAAgB,CAAC,KAAK;YACpB,4EAA4E;YAC5E,2EAA2E;YAC3E,2EAA2E;YAC3E,kEAAkE;YAClE,OAAO,OAAO,CAAC,sBAAsB,EAAE;gBACrC,iBAAiB,EAAE,YAAY;gBAC/B,GAAG,CAAC,KAAK,KAAK,SAAS;oBACrB,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;oBAC9B,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;aACzD,EAAE,KAAK,CAAC,CAAA;QACX,CAAC;QACD,IAAI;YACF,0EAA0E;YAC1E,sEAAsE;YACtE,yEAAyE;YACzE,uEAAuE;YACvE,0CAA0C;YAC1C,MAAM,GAAG,IAAI,CAAA;YACb,MAAM,SAAS,GAAG,MAAM,CAAA;YACxB,MAAM,GAAG,EAAE,CAAA;YACX,KAAK,MAAM,KAAK,IAAI,SAAS;gBAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACpD,CAAC;QACD,KAAK,CAAC,MAAM;YACV,yEAAyE;YACzE,0EAA0E;YAC1E,uEAAuE;YACvE,qEAAqE;YACrE,2CAA2C;YAC3C,IAAI,CAAC,OAAO;gBAAE,OAAM;YACpB,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;gBAChC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACvB,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoD;IACjF,MAAM,QAAQ,GAAkC,EAAE,CAAA;IAClD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAA;IAC/F,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AACrE,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,IAAY,EACZ,OAAoB,EACpB,QAAgB,EAChB,SAAiB,EACjB,OAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;IACvC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACvD,0EAA0E;QAC1E,yEAAyE;QACzE,IAAI,OAAO,EAAE;YAAE,OAAO,KAAK,CAAA;QAC3B,MAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACvC,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,KAAK,CAAA;QAChC,IAAI,MAAM,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC;YAAE,OAAO,IAAI,CAAA;IAC9D,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,OAAoB,EAAE,SAAiB;IACxE,OAAO,IAAI,OAAO,CAAU,OAAO,CAAC,EAAE;QACpC,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAA;QACrD,MAAM,MAAM,GAAa,EAAE,CAAA;QAC3B,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,IAAI,OAAO,GAAG,KAAK,CAAA;QAEnB,MAAM,MAAM,GAAG,CAAC,SAAkB,EAAQ,EAAE;YAC1C,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,YAAY,CAAC,MAAM,CAAC,CAAA;YACpB,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,OAAO,CAAC,SAAS,CAAC,CAAA;QACpB,CAAC,CAAA;QAED,4EAA4E;QAC5E,mCAAmC;QACnC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAA;QACzD,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QACjD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QACzC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,kBAAkB,EAAE,CAAC,CAAC,CAAA;QAC7F,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAA;YAC5B,IAAI,QAAQ,GAAG,kBAAkB,EAAE,CAAC;gBAClC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACb,OAAM;YACR,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClB,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YACjE,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;YAChD,uEAAuE;YACvE,iEAAiE;YACjE,IAAI,GAAG,IAAI,CAAC;gBAAE,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;QACrE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,QAAgB,EAAE,SAAiB;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAY,CAAA;QAC9C,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,IAAI,QAAQ,IAAI,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,CAAA;IAClG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC"}
@@ -60,6 +60,8 @@ export declare const DEFAULT_ATTEMPTS = 2;
60
60
  export declare const DEFAULT_TIMEOUT_MS = 500;
61
61
  /** A release on the way out cannot outlive the process that owes it. */
62
62
  export declare const EXIT_RELEASE_TIMEOUT_MS = 250;
63
+ /** The CLI to release through when the one Herdr exported cannot be spawned. */
64
+ export declare const FALLBACK_HERDR_BIN = "herdr";
63
65
  /** The first wait before a report Herdr did not acknowledge is sent again. */
64
66
  export declare const RETRY_BASE_MS = 250;
65
67
  /** The longest that wait can grow to, so a down socket is still noticed. */
@@ -83,6 +85,22 @@ export declare const MAX_METADATA_VALUE_CHARS = 80;
83
85
  * whole.
84
86
  */
85
87
  export declare const MAX_BLOCKED_MESSAGE_CHARS = 120;
88
+ /**
89
+ * The longest state label Herdr holds whole.
90
+ *
91
+ * Herdr shortens a longer one at its own limit, and a cut made server-side is one
92
+ * this surface can neither see nor test: bounding the label here keeps the
93
+ * ellipsis where the title meant it rather than wherever the multiplexer stopped.
94
+ */
95
+ export declare const MAX_STATE_LABEL_CHARS = 80;
96
+ /**
97
+ * The key a gate's wait is held under.
98
+ *
99
+ * Waits are keyed rather than counted because one modal slot can be taken over
100
+ * while it is still open: a count would then be incremented twice and given back
101
+ * once, and a row left blocked names a decision nobody owes any more.
102
+ */
103
+ export declare const GATE_WAIT_KEY = "gate";
86
104
  /**
87
105
  * Reports are sequenced in microseconds.
88
106
  *
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/herdr/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,wEAAwE;AACxE,eAAO,MAAM,cAAc,MAAM,CAAA;AAEjC,eAAO,MAAM,aAAa,cAAc,CAAA;AACxC,eAAO,MAAM,iBAAiB,kBAAkB,CAAA;AAChD,eAAO,MAAM,qBAAqB,sBAAsB,CAAA;AACxD,eAAO,MAAM,kBAAkB,mBAAmB,CAAA;AAElD,iFAAiF;AACjF,eAAO,MAAM,WAAW,QAAQ,CAAA;AAEhC;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,mBAAmB,CAAA;AAE5C,gDAAgD;AAChD,eAAO,MAAM,YAAY;;;;CAAoE,CAAA;AAC7F,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAA;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;;CAAoF,CAAA;AACtH,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAA;AAEnG;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;CAAsD,CAAA;AAElF,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAErC,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,MAAM,CAAA;AAE1C,8EAA8E;AAC9E,eAAO,MAAM,aAAa,MAAM,CAAA;AAEhC,4EAA4E;AAC5E,eAAO,MAAM,YAAY,OAAQ,CAAA;AAEjC,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,QAAY,CAAA;AAC3C,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,cAAc,OAAO,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/herdr/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,wEAAwE;AACxE,eAAO,MAAM,cAAc,MAAM,CAAA;AAEjC,eAAO,MAAM,aAAa,cAAc,CAAA;AACxC,eAAO,MAAM,iBAAiB,kBAAkB,CAAA;AAChD,eAAO,MAAM,qBAAqB,sBAAsB,CAAA;AACxD,eAAO,MAAM,kBAAkB,mBAAmB,CAAA;AAElD,iFAAiF;AACjF,eAAO,MAAM,WAAW,QAAQ,CAAA;AAEhC;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,mBAAmB,CAAA;AAE5C,gDAAgD;AAChD,eAAO,MAAM,YAAY;;;;CAAoE,CAAA;AAC7F,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAA;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;;CAAoF,CAAA;AACtH,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAA;AAEnG;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;CAAsD,CAAA;AAElF,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAErC,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,MAAM,CAAA;AAE1C,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,UAAU,CAAA;AAEzC,8EAA8E;AAC9E,eAAO,MAAM,aAAa,MAAM,CAAA;AAEhC,4EAA4E;AAC5E,eAAO,MAAM,YAAY,OAAQ,CAAA;AAEjC,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,QAAY,CAAA;AAC3C,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAA;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,SAAS,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,OAAO,CAAA"}
@@ -46,6 +46,8 @@ export const DEFAULT_ATTEMPTS = 2;
46
46
  export const DEFAULT_TIMEOUT_MS = 500;
47
47
  /** A release on the way out cannot outlive the process that owes it. */
48
48
  export const EXIT_RELEASE_TIMEOUT_MS = 250;
49
+ /** The CLI to release through when the one Herdr exported cannot be spawned. */
50
+ export const FALLBACK_HERDR_BIN = 'herdr';
49
51
  /** The first wait before a report Herdr did not acknowledge is sent again. */
50
52
  export const RETRY_BASE_MS = 250;
51
53
  /** The longest that wait can grow to, so a down socket is still noticed. */
@@ -69,6 +71,22 @@ export const MAX_METADATA_VALUE_CHARS = 80;
69
71
  * whole.
70
72
  */
71
73
  export const MAX_BLOCKED_MESSAGE_CHARS = 120;
74
+ /**
75
+ * The longest state label Herdr holds whole.
76
+ *
77
+ * Herdr shortens a longer one at its own limit, and a cut made server-side is one
78
+ * this surface can neither see nor test: bounding the label here keeps the
79
+ * ellipsis where the title meant it rather than wherever the multiplexer stopped.
80
+ */
81
+ export const MAX_STATE_LABEL_CHARS = 80;
82
+ /**
83
+ * The key a gate's wait is held under.
84
+ *
85
+ * Waits are keyed rather than counted because one modal slot can be taken over
86
+ * while it is still open: a count would then be incremented twice and given back
87
+ * once, and a row left blocked names a decision nobody owes any more.
88
+ */
89
+ export const GATE_WAIT_KEY = 'gate';
72
90
  /**
73
91
  * Reports are sequenced in microseconds.
74
92
  *