@sentropic/h2a-runtime 0.89.0 → 0.90.1

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/index.d.ts CHANGED
@@ -142,6 +142,13 @@ export { main as dispatch };
142
142
  */
143
143
  export declare function projectAgentsForH2a(): ReturnType<typeof projectRemoteAgents>;
144
144
  export { projectStatusForH2a };
145
+ /**
146
+ * Status-bar writer surface, consumed by `@sentropic/h2a`'s
147
+ * `status --write-bars` loop via lazy `import()`: enumerate the sessions whose
148
+ * installed bar expects prepared files, and resolve where those files live.
149
+ */
150
+ export { listStatusBarTargets, statusBarFilesForSession, statusBarRoot } from "./tmux.js";
151
+ export type { StatusBarTarget } from "./tmux.js";
145
152
  /** Open the detailed watcher only for an exact, currently managed session. */
146
153
  export declare function openStatusWindowForH2a(session: string): boolean;
147
154
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -15,16 +15,16 @@ import { transmittedSecrets, secretsSummary } from "./secrets.js";
15
15
  import { localConvStat, remoteConvStat, alignment } from "./convsync.js";
16
16
  import { gitAlignment, localAncestry, localGitStat, remoteGitStat, } from "./gitdiff.js";
17
17
  import { syncConversation } from "./sync.js";
18
- import { attachLocalSession, attachPodTmux, capturePane, capturePaneVisible, clearPaneComposer, conductorRunning, currentTmuxSessionName, currentTmuxSessionIs, ensureManagedTmuxProfile, ensureHeadlessTerminal, existingLocalSessionSlugs, fanoutLabels, findLocalSession, killLocalSession, localSessionGatewayEnvStatus, listLocalSessions, localSessionIdle, localSessionPanePid, localSessionName, paneTreeCpuMs, paneWorkerPid, pasteLiteralBlock, submitPane, installH2aStatusSurface, managedSessionCandidates, parseManagedSessionName, openH2aStatusWindow, persistLaunchContext, readLaunchContext, relaunchInSession, resolveAgentPane, resolveAgentPaneForInstance, resolveLocalSession, runLocalCliForeground, sendKeysLiteral, sessionAttached, sessionAttachedCount, setLocalSessionDisplayName, slugify, cleanupHeadlessPromptFile, startH2aWindow, startH2aWindowVerified, startHeadlessSession, startLocalSession, tmuxAvailable, uninstallH2aStatusSurface, } from "./tmux.js";
18
+ import { attachLocalSession, attachPodTmux, capturePane, capturePaneVisible, clearPaneComposer, conductorRunning, currentTmuxSessionName, currentTmuxSessionIs, ensureManagedTmuxProfile, ensureHeadlessTerminal, existingLocalSessionSlugs, fanoutLabels, findLocalSession, killLocalSession, localSessionGatewayEnvStatus, listLocalSessions, listLocalSessionsWithDiagnostics, localSessionIdle, localSessionPanePid, localSessionName, paneTreeCpuMs, paneWorkerPid, pasteLiteralBlock, submitPane, installH2aStatusSurface, managedSessionCandidates, parseManagedSessionName, openH2aStatusWindow, persistLaunchContext, readLaunchContext, relaunchInSession, resolveAgentPane, resolveAgentPaneForInstance, resolveLocalSession, runLocalCliForeground, sendKeysLiteral, sessionAttached, sessionAttachedCount, setLocalSessionDisplayName, slugify, cleanupHeadlessPromptFile, startH2aWindow, startH2aWindowVerified, startHeadlessSession, startLocalSession, tmuxAvailable, uninstallH2aStatusSurface, } from "./tmux.js";
19
19
  import { deliverInitialPrompt, sleepSync, } from "./prompt-delivery.js";
20
20
  import { buildLaunchContext } from "./launch-context.js";
21
21
  import { migrateTmuxNames } from "./tmux-name-migration.js";
22
22
  import { projectStatusForH2a } from "./status-projection.js";
23
23
  import { buildAgentLaunchArgs, isAgentLaunchEffort, isAgentLaunchProfile, } from "./agent-launch-args.js";
24
24
  import { planRelaunch } from "./relaunch.js";
25
- import { isHumanFacingSession, readLastLayout, restore as restoreLayout, } from "./restore.js";
25
+ import { isHumanFacingSession, readConversationCustomTitle, readLastLayout, reconcileRunConvIds, restore as restoreLayout, } from "./restore.js";
26
26
  import { getLayoutConfig } from "./config.js";
27
- import { advanceJob, coerceRegistryTool, enroll, enrollFromRun, isLive, listJobs, listLocalForLs, loadRegistry, resolveLocalTmuxSessionForName, tryClaimSlot, withRegistryLock, resolveRegistryPath, } from "./registry.js";
27
+ import { advanceJob, coerceRegistryTool, enroll, enrollFromRun, isLive, listJobs, listLocalForLs, loadRegistry, loadRegistryWithDiagnostics, resolveLocalTmuxSessionForName, tryClaimSlot, withRegistryLock, resolveRegistryPath, } from "./registry.js";
28
28
  import { SessionLeaseStore, decideSessionBeat, isSessionLeaseAbandoned, planLeaseSupervision, reclaimProposals, resolveSessionLeasePath, } from "./session-lease.js";
29
29
  import { aimdEffectiveCap, assertDelegateEffort, assertSafeName, buildDelegateArgs, buildJobRows, buildRemoteDelegate, buildThrottleResumeArgs, canDelegateAtDepth, childDepthEnvValue, clampDepth, clampRemoteDepthBudget, conductorAdvisory, DEFAULT_MAX_CONCURRENT, DEPTH_ENV, inheritedDepthBudget, isDelegateType, isThrottleResumeDue, jitteredBackoffMs, JOB_ID_ENV, jobDir, planNextStarts, planThrottleStep, readJobResult, THROTTLE_MAX_ATTEMPTS, reconcileRemoteJobs, renderJobsTable, resolveJobCwd, runTrackMirror, sweepStaleJobs, trackItemNewArgs, trackItemRealizeArgs, } from "./delegate.js";
30
30
  import { detectThrottle, THROTTLE_TAIL_LINES } from "./throttle-signatures.js";
@@ -1422,7 +1422,7 @@ async function prepareLlmMeshForRestore(opts = {}) {
1422
1422
  process.stderr.write(`[h2a] llm-mesh: restore context active (${gateway})\n`);
1423
1423
  }
1424
1424
  }
1425
- function registryEntryForResumeTarget(target, local) {
1425
+ function registryEntriesForLocalTmuxTarget(target, local, entries = loadRegistry()) {
1426
1426
  const parsedTarget = parseManagedSessionName(target);
1427
1427
  const canonicalSlug = local?.slug ?? parsedTarget?.slug ?? target;
1428
1428
  const tmuxSession = local?.name ?? target;
@@ -1431,19 +1431,8 @@ function registryEntryForResumeTarget(target, local) {
1431
1431
  : parsedTarget
1432
1432
  ? [target]
1433
1433
  : managedSessionCandidates(canonicalSlug);
1434
- const matches = loadRegistry().filter((e) => {
1435
- // Resume is a human-facing operation, not a promotion path: a delegated job
1436
- // or an explicit background launch must never become resumable here.
1437
- //
1438
- // The class test is SHARED with restore rather than written inline, because
1439
- // written inline it was an opt-in on an explicit class and every record
1440
- // enrolled before the class existed failed closed — measured as "cannot
1441
- // resume <slug>: registry has no human session" on entries that are plainly
1442
- // human sessions. Two gates judging the same question in two ways is how one
1443
- // of them ends up wrong on its own.
1444
- if (e.role !== undefined || e.kind !== "local-tmux")
1445
- return false;
1446
- if (!isHumanFacingSession(e))
1434
+ return entries.filter((e) => {
1435
+ if (e.kind !== "local-tmux")
1447
1436
  return false;
1448
1437
  // Full managed names are exact targets; never reinterpret one as an id
1449
1438
  // or label that happens to share a prefix-shaped string.
@@ -1458,6 +1447,16 @@ function registryEntryForResumeTarget(target, local) {
1458
1447
  e.tmuxSession === tmuxSession ||
1459
1448
  (e.tmuxSession !== undefined && candidates.includes(e.tmuxSession)));
1460
1449
  });
1450
+ }
1451
+ function registryEntryForResumeTarget(target, local) {
1452
+ const matches = registryEntriesForLocalTmuxTarget(target, local).filter((e) => {
1453
+ // Resume is a human-facing operation, not a promotion path. Share the
1454
+ // durable class test with restore so legacy human rows remain resumable,
1455
+ // while delegated jobs and explicit background launches stay excluded.
1456
+ if (e.role !== undefined)
1457
+ return false;
1458
+ return isHumanFacingSession(e);
1459
+ });
1461
1460
  const ids = new Set(matches.map((e) => e.id));
1462
1461
  if (ids.size !== 1)
1463
1462
  return undefined;
@@ -1512,6 +1511,23 @@ async function confirmReplace(slug) {
1512
1511
  rl.close();
1513
1512
  }
1514
1513
  }
1514
+ async function confirmRelaunchAll() {
1515
+ if (process.stdin.isTTY !== true || process.stderr.isTTY !== true) {
1516
+ return false;
1517
+ }
1518
+ const { createInterface: createPromisesInterface } = await import("node:readline/promises");
1519
+ const rl = createPromisesInterface({
1520
+ input: process.stdin,
1521
+ output: process.stderr,
1522
+ });
1523
+ try {
1524
+ const answer = await rl.question('Type "RELAUNCH" to force-restart every listed session: ');
1525
+ return answer.trim() === "RELAUNCH";
1526
+ }
1527
+ finally {
1528
+ rl.close();
1529
+ }
1530
+ }
1515
1531
  function resolveUrlAndSessionId(first, second) {
1516
1532
  if (second !== undefined) {
1517
1533
  return { url: getConfiguredRemote(first), sessionId: second };
@@ -5372,42 +5388,105 @@ export async function main(argv) {
5372
5388
  process.stderr.write("[h2a] wake-request watch stopped\n");
5373
5389
  });
5374
5390
  // ---------------------------------------------------------------------------
5375
- // relaunch — bring idle local sessions back in situ, each resuming its OWN conv
5391
+ // relaunch — recover idle sessions, or explicitly force-recreate one/all
5376
5392
  // ---------------------------------------------------------------------------
5377
5393
  program
5378
5394
  .command("relaunch [filter]")
5379
- .description("Relaunch the CLI in local tmux sessions whose CLI dropped to a shell, in situ (windows kept), each resuming ITS OWN conversation from the registry. Running sessions are left alone. Dry-run by default; --apply to do it. [filter] = only sessions whose slug contains it.")
5395
+ .description("Dry-run local session recovery by default. With an exact [filter], --apply force-recreates that one session from its own registry conversation. --all force-recreates managed sessions only after a warning and typed confirmation (or --yes); interactive agent CLIs stay excluded unless --include-agents is explicit.")
5380
5396
  .option("--apply", "actually relaunch (default: dry-run, just print the plan)")
5381
- .action((filter, opts) => {
5397
+ .option("--all", "force-restart every managed local tmux session")
5398
+ .option("--yes", "confirm --all non-interactively (requires --apply)")
5399
+ .option("--include-agents", "with --all, include claude/codex/agy sessions that are excluded by default")
5400
+ .action(async (filter, opts) => {
5382
5401
  if (!tmuxAvailable()) {
5383
5402
  process.stderr.write("[h2a] tmux is not installed locally\n");
5384
5403
  process.exitCode = 1;
5385
5404
  return;
5386
5405
  }
5387
- // Exact tmux session -> its own convId when available. Historical rows
5388
- // fall back to their slug only after planRelaunch has excluded a dual
5389
- // h2a-/remote- prefix collision.
5390
- const convByTmuxSession = new Map();
5391
- const convBySlug = new Map();
5392
- for (const e of loadRegistry()) {
5393
- if (e.kind !== "local-tmux" || !e.convId)
5394
- continue;
5395
- convBySlug.set(e.id, e.convId);
5396
- if (e.tmuxSession)
5397
- convByTmuxSession.set(e.tmuxSession, e.convId);
5406
+ if (filter && opts.all) {
5407
+ process.stderr.write("[h2a] relaunch accepts either one exact session name or --all, not both.\n");
5408
+ process.exitCode = 1;
5409
+ return;
5410
+ }
5411
+ const inventory = listLocalSessionsWithDiagnostics();
5412
+ if (!inventory.known) {
5413
+ process.stderr.write(`[h2a] cannot safely relaunch: managed tmux inventory is unknown (${inventory.reason ?? "no detail"}).\n`);
5414
+ process.exitCode = 1;
5415
+ return;
5416
+ }
5417
+ let sessions = inventory.sessions;
5418
+ if (filter) {
5419
+ const exactName = parseManagedSessionName(filter) ? filter : undefined;
5420
+ const matches = exactName
5421
+ ? sessions.filter((session) => session.name === exactName)
5422
+ : sessions.filter((session) => session.slug === filter);
5423
+ if (matches.length !== 1) {
5424
+ const detail = matches.length
5425
+ ? `ambiguous (${matches.map((session) => session.name).join(", ")})`
5426
+ : "not found";
5427
+ process.stderr.write(`[h2a] cannot force-relaunch ${filter}: exact managed session is ${detail}.\n`);
5428
+ process.exitCode = 1;
5429
+ return;
5430
+ }
5431
+ sessions = matches;
5398
5432
  }
5399
- const sessions = listLocalSessions().filter((s) => !filter || s.slug.includes(filter));
5433
+ const forced = Boolean(filter || opts.all);
5434
+ const registry = loadRegistryWithDiagnostics();
5435
+ if (forced && !registry.known) {
5436
+ process.stderr.write(`[h2a] cannot safely force-relaunch: registry is unknown (${registry.reason ?? "no detail"}).\n`);
5437
+ process.exitCode = 1;
5438
+ return;
5439
+ }
5440
+ const registryEntries = registry.entries;
5441
+ const resolution = forced
5442
+ ? reconcileRunConvIds(registryEntries, (cwd, convId) => readConversationCustomTitle(homedir(), cwd, convId))
5443
+ : undefined;
5444
+ const entryByTmuxSession = new Map();
5400
5445
  const plan = planRelaunch(sessions.map((s) => ({
5446
+ ...(() => {
5447
+ const matches = registryEntriesForLocalTmuxTarget(s.name, s, registryEntries);
5448
+ const ids = new Set(matches.map((entry) => entry.id));
5449
+ const entry = matches.length === 1 && ids.size === 1
5450
+ ? matches
5451
+ .slice()
5452
+ .sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt))[0]
5453
+ : undefined;
5454
+ if (entry)
5455
+ entryByTmuxSession.set(s.name, entry);
5456
+ const resolvedConvId = entry
5457
+ ? resolution?.resolvedSid.get(entry.id) ?? entry.convId
5458
+ : undefined;
5459
+ const labelOnly = entry !== undefined &&
5460
+ (!resolvedConvId ||
5461
+ resolvedConvId === entry.id ||
5462
+ resolvedConvId === entry.label);
5463
+ return {
5464
+ profile: entry?.tool ?? s.profile,
5465
+ ...(matches.length > 1 || ids.size > 1
5466
+ ? { unresumableReason: "multiple registry rows match this tmux session — relaunch refused" }
5467
+ : !entry
5468
+ ? { unresumableReason: "no matching registry conversation — relaunch refused" }
5469
+ : entry.sessionClass === undefined
5470
+ ? { unresumableReason: "registry session class is missing — relaunch refused" }
5471
+ : labelOnly || resolution?.unresolvedRunIds.has(entry.id)
5472
+ ? { unresumableReason: "no resumable conversation in the registry — relaunch refused" }
5473
+ : resolvedConvId !== undefined
5474
+ ? { convId: resolvedConvId }
5475
+ : { unresumableReason: "no resumable conversation in the registry — relaunch refused" }),
5476
+ };
5477
+ })(),
5401
5478
  slug: s.slug,
5402
5479
  name: s.name,
5403
- profile: s.profile,
5404
5480
  idle: localSessionIdle(s.name),
5405
- ...(convByTmuxSession.has(s.name)
5406
- ? { convId: convByTmuxSession.get(s.name) }
5407
- : convBySlug.has(s.slug)
5408
- ? { convId: convBySlug.get(s.slug) }
5409
- : {}),
5410
- })));
5481
+ })), {
5482
+ ...(forced ? { force: true } : {}),
5483
+ ...(opts.all && !opts.includeAgents
5484
+ ? { excludeInteractiveAgents: true }
5485
+ : {}),
5486
+ });
5487
+ if (opts.all) {
5488
+ process.stderr.write(`[h2a] WARNING: force-restart plan covers ${sessions.length} managed session(s): ${sessions.map((session) => session.name).join(", ") || "none"}\n`);
5489
+ }
5411
5490
  if (plan.actions.length === 0) {
5412
5491
  process.stderr.write(`[h2a] nothing to relaunch${filter ? ` matching "${filter}"` : ""} (${plan.skipped.length} skipped)\n`);
5413
5492
  for (const s of plan.skipped) {
@@ -5416,7 +5495,7 @@ export async function main(argv) {
5416
5495
  return;
5417
5496
  }
5418
5497
  if (!opts.apply) {
5419
- process.stderr.write(`[h2a] would relaunch ${plan.actions.length} session(s) — dry-run, pass --apply:\n`);
5498
+ process.stderr.write(`[h2a] would${forced ? " force-restart" : " relaunch"} ${plan.actions.length} session(s) — dry-run, pass --apply:\n`);
5420
5499
  for (const a of plan.actions) {
5421
5500
  process.stderr.write(` ${a.slug}: ${a.cmd}\n`);
5422
5501
  }
@@ -5425,17 +5504,109 @@ export async function main(argv) {
5425
5504
  }
5426
5505
  return;
5427
5506
  }
5507
+ // Backward-compatible crash recovery: bare `relaunch --apply` only
5508
+ // retypes into idle shells. Forced kill/recreate is available solely for
5509
+ // one exact target or explicit `--all`.
5510
+ if (!forced) {
5511
+ let ok = 0;
5512
+ for (const action of plan.actions) {
5513
+ if (relaunchInSession(action.name, action.cmd)) {
5514
+ ok += 1;
5515
+ process.stderr.write(`[h2a] relaunched ${action.slug}: ${action.cmd}\n`);
5516
+ }
5517
+ else {
5518
+ process.stderr.write(`[h2a] FAILED to relaunch ${action.slug}\n`);
5519
+ }
5520
+ }
5521
+ process.stderr.write(`[h2a] relaunched ${ok}/${plan.actions.length}${plan.skipped.length ? `, ${plan.skipped.length} skipped` : ""}\n`);
5522
+ if (ok !== plan.actions.length)
5523
+ process.exitCode = 1;
5524
+ return;
5525
+ }
5526
+ if (opts.all && !opts.yes && !(await confirmRelaunchAll())) {
5527
+ process.stderr.write("[h2a] bulk force-restart requires typing RELAUNCH, or pass --yes for non-interactive use. No session was changed.\n");
5528
+ process.exitCode = 1;
5529
+ return;
5530
+ }
5531
+ for (const skipped of plan.skipped) {
5532
+ process.stderr.write(`[h2a] skipped ${skipped.slug}: ${skipped.reason}\n`);
5533
+ }
5534
+ if (filter) {
5535
+ process.stderr.write(`[h2a] confirmed force-restart of ${plan.actions[0].slug}; its tmux session will be replaced.\n`);
5536
+ }
5537
+ const ready = [];
5538
+ let preflightFailed = false;
5539
+ for (const action of plan.actions) {
5540
+ const entry = entryByTmuxSession.get(action.name);
5541
+ const sessionClass = entry?.sessionClass;
5542
+ if (!entry || sessionClass === undefined) {
5543
+ preflightFailed = true;
5544
+ process.stderr.write(`[h2a] cannot force-restart ${action.slug}: its registry launch context changed; no session was killed.\n`);
5545
+ continue;
5546
+ }
5547
+ const allowed = await guardConvWriters({
5548
+ convId: action.convId,
5549
+ cwd: entry.cwd,
5550
+ excludeId: entry.id,
5551
+ fetchRemoteSessions: async () => {
5552
+ const url = getConfiguredRemoteOptional();
5553
+ return url ? await listRemoteSessions(url) : [];
5554
+ },
5555
+ });
5556
+ if (!allowed) {
5557
+ preflightFailed = true;
5558
+ continue;
5559
+ }
5560
+ ready.push({ action, entry, sessionClass });
5561
+ }
5562
+ const rechecked = listLocalSessionsWithDiagnostics();
5563
+ if (!rechecked.known) {
5564
+ process.stderr.write(`[h2a] cannot safely force-restart: managed tmux inventory changed (${rechecked.reason ?? "no detail"}). No session was killed.\n`);
5565
+ process.exitCode = 1;
5566
+ return;
5567
+ }
5568
+ for (const { action } of ready) {
5569
+ if (!rechecked.sessions.some((session) => session.name === action.name)) {
5570
+ preflightFailed = true;
5571
+ process.stderr.write(`[h2a] cannot force-restart ${action.slug}: its tmux session changed before replacement. No session was killed.\n`);
5572
+ }
5573
+ }
5574
+ if (preflightFailed) {
5575
+ process.stderr.write("[h2a] force-restart aborted before any session was killed.\n");
5576
+ process.exitCode = 1;
5577
+ return;
5578
+ }
5428
5579
  let ok = 0;
5429
- for (const a of plan.actions) {
5430
- if (relaunchInSession(a.name, a.cmd)) {
5580
+ for (const { action, entry, sessionClass } of ready) {
5581
+ if (!killLocalSession(action.name)) {
5582
+ process.stderr.write(`[h2a] FAILED to force-restart ${action.slug}: tmux session ${action.name} could not be killed.\n`);
5583
+ continue;
5584
+ }
5585
+ try {
5586
+ const gatewayMode = gatewayModeForProfile(action.profile, entry.gatewayMode ?? "auto");
5587
+ await injectLlmMeshGatewayEnv(gatewayMode, true, localSessionName(action.slug));
5588
+ const { name } = startLocalSession(action.profile, action.command, entry.cwd, action.args, action.slug, undefined, { sessionClass });
5589
+ enrollFromRun({
5590
+ profile: action.profile,
5591
+ slug: action.slug,
5592
+ tmuxSession: name,
5593
+ cwd: entry.cwd,
5594
+ sessionClass,
5595
+ convId: action.convId,
5596
+ ...(entry.gatewayMode !== undefined
5597
+ ? { gatewayMode: entry.gatewayMode }
5598
+ : {}),
5599
+ });
5431
5600
  ok += 1;
5432
- process.stderr.write(`[h2a] relaunched ${a.slug}: ${a.cmd}\n`);
5601
+ process.stderr.write(`[h2a] force-restarted ${action.slug}: ${action.cmd}\n`);
5433
5602
  }
5434
- else {
5435
- process.stderr.write(`[h2a] FAILED to relaunch ${a.slug}\n`);
5603
+ catch (error) {
5604
+ process.stderr.write(`[h2a] FAILED to force-restart ${action.slug} after killing ${action.name}: ${error.message}\n`);
5436
5605
  }
5437
5606
  }
5438
- process.stderr.write(`[h2a] relaunched ${ok}/${plan.actions.length}${plan.skipped.length ? `, ${plan.skipped.length} skipped` : ""}\n`);
5607
+ process.stderr.write(`[h2a] force-restarted ${ok}/${plan.actions.length}${plan.skipped.length ? `, ${plan.skipped.length} skipped` : ""}\n`);
5608
+ if (ok !== plan.actions.length)
5609
+ process.exitCode = 1;
5439
5610
  });
5440
5611
  // ---------------------------------------------------------------------------
5441
5612
  // Reliability slice 2 (throttle phase 2) — auto-resume RATE-LIMITED INTERACTIVE
@@ -6864,6 +7035,12 @@ export function projectAgentsForH2a() {
6864
7035
  return projectRemoteAgents({ jobs: listJobs(), localRows: listLocalForLs() });
6865
7036
  }
6866
7037
  export { projectStatusForH2a };
7038
+ /**
7039
+ * Status-bar writer surface, consumed by `@sentropic/h2a`'s
7040
+ * `status --write-bars` loop via lazy `import()`: enumerate the sessions whose
7041
+ * installed bar expects prepared files, and resolve where those files live.
7042
+ */
7043
+ export { listStatusBarTargets, statusBarFilesForSession, statusBarRoot } from "./tmux.js";
6867
7044
  /** Open the detailed watcher only for an exact, currently managed session. */
6868
7045
  export function openStatusWindowForH2a(session) {
6869
7046
  const exact = listLocalSessions().find((item) => item.name === session);