@askexenow/exe-os 0.9.115 → 0.9.116

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 (42) hide show
  1. package/dist/bin/cleanup-stale-review-tasks.js +16 -3
  2. package/dist/bin/cli.js +31 -3
  3. package/dist/bin/exe-boot.js +31 -3
  4. package/dist/bin/exe-dispatch.js +31 -3
  5. package/dist/bin/exe-gateway.js +31 -3
  6. package/dist/bin/exe-heartbeat.js +16 -3
  7. package/dist/bin/exe-pending-messages.js +16 -3
  8. package/dist/bin/exe-pending-notifications.js +16 -3
  9. package/dist/bin/exe-pending-reviews.js +16 -3
  10. package/dist/bin/exe-session-cleanup.js +31 -3
  11. package/dist/bin/exe-status.js +16 -3
  12. package/dist/bin/git-sweep.js +31 -3
  13. package/dist/bin/intercom-check.js +31 -3
  14. package/dist/bin/scan-tasks.js +31 -3
  15. package/dist/gateway/index.js +31 -3
  16. package/dist/hooks/bug-report-worker.js +31 -3
  17. package/dist/hooks/codex-stop-task-finalizer.js +31 -3
  18. package/dist/hooks/commit-complete.js +31 -3
  19. package/dist/hooks/ingest.js +31 -3
  20. package/dist/hooks/post-compact.js +16 -3
  21. package/dist/hooks/post-tool-combined.js +16 -3
  22. package/dist/hooks/pre-compact.js +31 -3
  23. package/dist/hooks/pre-tool-use.js +16 -3
  24. package/dist/hooks/prompt-submit.js +31 -3
  25. package/dist/hooks/session-end.js +31 -3
  26. package/dist/hooks/session-start.js +16 -3
  27. package/dist/hooks/stop.js +16 -3
  28. package/dist/hooks/subagent-stop.js +16 -3
  29. package/dist/hooks/summary-worker.js +16 -3
  30. package/dist/index.js +31 -3
  31. package/dist/lib/exe-daemon.js +31 -3
  32. package/dist/lib/messaging.js +31 -3
  33. package/dist/lib/tasks.js +31 -3
  34. package/dist/lib/tmux-routing.js +31 -3
  35. package/dist/mcp/server.js +31 -3
  36. package/dist/mcp/tools/create-task.js +31 -3
  37. package/dist/mcp/tools/list-tasks.js +16 -3
  38. package/dist/mcp/tools/send-message.js +31 -3
  39. package/dist/mcp/tools/update-task.js +31 -3
  40. package/dist/runtime/index.js +31 -3
  41. package/dist/tui/App.js +31 -3
  42. package/package.json +1 -1
@@ -8158,15 +8158,28 @@ function getDispatchedBy(sessionKey) {
8158
8158
  }
8159
8159
  }
8160
8160
  function resolveExeSession() {
8161
+ const mySession = getMySession();
8162
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
8161
8163
  if (process.env.EXE_SESSION_NAME) {
8162
8164
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
8163
- if (fromEnv) return fromEnv;
8165
+ if (fromEnv) {
8166
+ if (!mySession) {
8167
+ return fromEnv;
8168
+ }
8169
+ if (fromSessionName && fromEnv !== fromSessionName) {
8170
+ process.stderr.write(
8171
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
8172
+ `
8173
+ );
8174
+ process.env.EXE_SESSION_NAME = fromSessionName;
8175
+ } else {
8176
+ return fromEnv;
8177
+ }
8178
+ }
8164
8179
  }
8165
- const mySession = getMySession();
8166
8180
  if (!mySession) {
8167
8181
  return null;
8168
8182
  }
8169
- const fromSessionName = extractRootExe(mySession);
8170
8183
  let candidate = null;
8171
8184
  try {
8172
8185
  const key = getSessionKey();
@@ -8350,6 +8363,21 @@ function isExeSession(sessionName) {
8350
8363
  }
8351
8364
  function sendIntercom(targetSession) {
8352
8365
  const transport = getTransport();
8366
+ try {
8367
+ const callerScope = resolveExeSession();
8368
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
8369
+ const targetScope = extractRootExe(targetSession);
8370
+ if (targetScope && targetScope !== callerScope) {
8371
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
8372
+ process.stderr.write(
8373
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
8374
+ `
8375
+ );
8376
+ return "failed";
8377
+ }
8378
+ }
8379
+ } catch {
8380
+ }
8353
8381
  if (isExeSession(targetSession)) {
8354
8382
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
8355
8383
  return "skipped_exe";
@@ -7205,15 +7205,28 @@ function getDispatchedBy(sessionKey) {
7205
7205
  }
7206
7206
  }
7207
7207
  function resolveExeSession() {
7208
+ const mySession = getMySession();
7209
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
7208
7210
  if (process.env.EXE_SESSION_NAME) {
7209
7211
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
7210
- if (fromEnv) return fromEnv;
7212
+ if (fromEnv) {
7213
+ if (!mySession) {
7214
+ return fromEnv;
7215
+ }
7216
+ if (fromSessionName && fromEnv !== fromSessionName) {
7217
+ process.stderr.write(
7218
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
7219
+ `
7220
+ );
7221
+ process.env.EXE_SESSION_NAME = fromSessionName;
7222
+ } else {
7223
+ return fromEnv;
7224
+ }
7225
+ }
7211
7226
  }
7212
- const mySession = getMySession();
7213
7227
  if (!mySession) {
7214
7228
  return null;
7215
7229
  }
7216
- const fromSessionName = extractRootExe(mySession);
7217
7230
  let candidate = null;
7218
7231
  try {
7219
7232
  const key = getSessionKey();
@@ -7355,6 +7368,21 @@ function isExeSession(sessionName) {
7355
7368
  }
7356
7369
  function sendIntercom(targetSession) {
7357
7370
  const transport = getTransport();
7371
+ try {
7372
+ const callerScope = resolveExeSession();
7373
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
7374
+ const targetScope = extractRootExe(targetSession);
7375
+ if (targetScope && targetScope !== callerScope) {
7376
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
7377
+ process.stderr.write(
7378
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
7379
+ `
7380
+ );
7381
+ return "failed";
7382
+ }
7383
+ }
7384
+ } catch {
7385
+ }
7358
7386
  if (isExeSession(targetSession)) {
7359
7387
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
7360
7388
  return "skipped_exe";
@@ -7506,15 +7506,28 @@ function getDispatchedBy(sessionKey) {
7506
7506
  }
7507
7507
  }
7508
7508
  function resolveExeSession() {
7509
+ const mySession = getMySession();
7510
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
7509
7511
  if (process.env.EXE_SESSION_NAME) {
7510
7512
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
7511
- if (fromEnv) return fromEnv;
7513
+ if (fromEnv) {
7514
+ if (!mySession) {
7515
+ return fromEnv;
7516
+ }
7517
+ if (fromSessionName && fromEnv !== fromSessionName) {
7518
+ process.stderr.write(
7519
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
7520
+ `
7521
+ );
7522
+ process.env.EXE_SESSION_NAME = fromSessionName;
7523
+ } else {
7524
+ return fromEnv;
7525
+ }
7526
+ }
7512
7527
  }
7513
- const mySession = getMySession();
7514
7528
  if (!mySession) {
7515
7529
  return null;
7516
7530
  }
7517
- const fromSessionName = extractRootExe(mySession);
7518
7531
  let candidate = null;
7519
7532
  try {
7520
7533
  const key = getSessionKey();
@@ -7698,6 +7711,21 @@ function isExeSession(sessionName) {
7698
7711
  }
7699
7712
  function sendIntercom(targetSession) {
7700
7713
  const transport = getTransport();
7714
+ try {
7715
+ const callerScope = resolveExeSession();
7716
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
7717
+ const targetScope = extractRootExe(targetSession);
7718
+ if (targetScope && targetScope !== callerScope) {
7719
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
7720
+ process.stderr.write(
7721
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
7722
+ `
7723
+ );
7724
+ return "failed";
7725
+ }
7726
+ }
7727
+ } catch {
7728
+ }
7701
7729
  if (isExeSession(targetSession)) {
7702
7730
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
7703
7731
  return "skipped_exe";
@@ -9383,15 +9383,28 @@ function getDispatchedBy(sessionKey) {
9383
9383
  }
9384
9384
  }
9385
9385
  function resolveExeSession() {
9386
+ const mySession = getMySession();
9387
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
9386
9388
  if (process.env.EXE_SESSION_NAME) {
9387
9389
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
9388
- if (fromEnv) return fromEnv;
9390
+ if (fromEnv) {
9391
+ if (!mySession) {
9392
+ return fromEnv;
9393
+ }
9394
+ if (fromSessionName && fromEnv !== fromSessionName) {
9395
+ process.stderr.write(
9396
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
9397
+ `
9398
+ );
9399
+ process.env.EXE_SESSION_NAME = fromSessionName;
9400
+ } else {
9401
+ return fromEnv;
9402
+ }
9403
+ }
9389
9404
  }
9390
- const mySession = getMySession();
9391
9405
  if (!mySession) {
9392
9406
  return null;
9393
9407
  }
9394
- const fromSessionName = extractRootExe(mySession);
9395
9408
  let candidate = null;
9396
9409
  try {
9397
9410
  const key = getSessionKey();
@@ -9575,6 +9588,21 @@ function isExeSession(sessionName) {
9575
9588
  }
9576
9589
  function sendIntercom(targetSession) {
9577
9590
  const transport = getTransport();
9591
+ try {
9592
+ const callerScope = resolveExeSession();
9593
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
9594
+ const targetScope = extractRootExe(targetSession);
9595
+ if (targetScope && targetScope !== callerScope) {
9596
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
9597
+ process.stderr.write(
9598
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
9599
+ `
9600
+ );
9601
+ return "failed";
9602
+ }
9603
+ }
9604
+ } catch {
9605
+ }
9578
9606
  if (isExeSession(targetSession)) {
9579
9607
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
9580
9608
  return "skipped_exe";
@@ -4043,15 +4043,28 @@ function getParentExe(sessionKey) {
4043
4043
  }
4044
4044
  }
4045
4045
  function resolveExeSession() {
4046
+ const mySession = getMySession();
4047
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
4046
4048
  if (process.env.EXE_SESSION_NAME) {
4047
4049
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
4048
- if (fromEnv) return fromEnv;
4050
+ if (fromEnv) {
4051
+ if (!mySession) {
4052
+ return fromEnv;
4053
+ }
4054
+ if (fromSessionName && fromEnv !== fromSessionName) {
4055
+ process.stderr.write(
4056
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
4057
+ `
4058
+ );
4059
+ process.env.EXE_SESSION_NAME = fromSessionName;
4060
+ } else {
4061
+ return fromEnv;
4062
+ }
4063
+ }
4049
4064
  }
4050
- const mySession = getMySession();
4051
4065
  if (!mySession) {
4052
4066
  return null;
4053
4067
  }
4054
- const fromSessionName = extractRootExe(mySession);
4055
4068
  let candidate = null;
4056
4069
  try {
4057
4070
  const key = getSessionKey();
@@ -9122,15 +9122,28 @@ function getParentExe(sessionKey) {
9122
9122
  }
9123
9123
  }
9124
9124
  function resolveExeSession() {
9125
+ const mySession = getMySession();
9126
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
9125
9127
  if (process.env.EXE_SESSION_NAME) {
9126
9128
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
9127
- if (fromEnv) return fromEnv;
9129
+ if (fromEnv) {
9130
+ if (!mySession) {
9131
+ return fromEnv;
9132
+ }
9133
+ if (fromSessionName && fromEnv !== fromSessionName) {
9134
+ process.stderr.write(
9135
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
9136
+ `
9137
+ );
9138
+ process.env.EXE_SESSION_NAME = fromSessionName;
9139
+ } else {
9140
+ return fromEnv;
9141
+ }
9142
+ }
9128
9143
  }
9129
- const mySession = getMySession();
9130
9144
  if (!mySession) {
9131
9145
  return null;
9132
9146
  }
9133
- const fromSessionName = extractRootExe(mySession);
9134
9147
  let candidate = null;
9135
9148
  try {
9136
9149
  const key = getSessionKey();
@@ -7490,15 +7490,28 @@ function getDispatchedBy(sessionKey) {
7490
7490
  }
7491
7491
  }
7492
7492
  function resolveExeSession() {
7493
+ const mySession = getMySession();
7494
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
7493
7495
  if (process.env.EXE_SESSION_NAME) {
7494
7496
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
7495
- if (fromEnv) return fromEnv;
7497
+ if (fromEnv) {
7498
+ if (!mySession) {
7499
+ return fromEnv;
7500
+ }
7501
+ if (fromSessionName && fromEnv !== fromSessionName) {
7502
+ process.stderr.write(
7503
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
7504
+ `
7505
+ );
7506
+ process.env.EXE_SESSION_NAME = fromSessionName;
7507
+ } else {
7508
+ return fromEnv;
7509
+ }
7510
+ }
7496
7511
  }
7497
- const mySession = getMySession();
7498
7512
  if (!mySession) {
7499
7513
  return null;
7500
7514
  }
7501
- const fromSessionName = extractRootExe(mySession);
7502
7515
  let candidate = null;
7503
7516
  try {
7504
7517
  const key = getSessionKey();
@@ -7682,6 +7695,21 @@ function isExeSession(sessionName) {
7682
7695
  }
7683
7696
  function sendIntercom(targetSession) {
7684
7697
  const transport = getTransport();
7698
+ try {
7699
+ const callerScope = resolveExeSession();
7700
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
7701
+ const targetScope = extractRootExe(targetSession);
7702
+ if (targetScope && targetScope !== callerScope) {
7703
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
7704
+ process.stderr.write(
7705
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
7706
+ `
7707
+ );
7708
+ return "failed";
7709
+ }
7710
+ }
7711
+ } catch {
7712
+ }
7685
7713
  if (isExeSession(targetSession)) {
7686
7714
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
7687
7715
  return "skipped_exe";
@@ -4043,15 +4043,28 @@ function getParentExe(sessionKey) {
4043
4043
  }
4044
4044
  }
4045
4045
  function resolveExeSession() {
4046
+ const mySession = getMySession();
4047
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
4046
4048
  if (process.env.EXE_SESSION_NAME) {
4047
4049
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
4048
- if (fromEnv) return fromEnv;
4050
+ if (fromEnv) {
4051
+ if (!mySession) {
4052
+ return fromEnv;
4053
+ }
4054
+ if (fromSessionName && fromEnv !== fromSessionName) {
4055
+ process.stderr.write(
4056
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
4057
+ `
4058
+ );
4059
+ process.env.EXE_SESSION_NAME = fromSessionName;
4060
+ } else {
4061
+ return fromEnv;
4062
+ }
4063
+ }
4049
4064
  }
4050
- const mySession = getMySession();
4051
4065
  if (!mySession) {
4052
4066
  return null;
4053
4067
  }
4054
- const fromSessionName = extractRootExe(mySession);
4055
4068
  let candidate = null;
4056
4069
  try {
4057
4070
  const key = getSessionKey();
@@ -11130,15 +11130,28 @@ function getDispatchedBy(sessionKey) {
11130
11130
  }
11131
11131
  }
11132
11132
  function resolveExeSession() {
11133
+ const mySession = getMySession();
11134
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
11133
11135
  if (process.env.EXE_SESSION_NAME) {
11134
11136
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
11135
- if (fromEnv) return fromEnv;
11137
+ if (fromEnv) {
11138
+ if (!mySession) {
11139
+ return fromEnv;
11140
+ }
11141
+ if (fromSessionName && fromEnv !== fromSessionName) {
11142
+ process.stderr.write(
11143
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
11144
+ `
11145
+ );
11146
+ process.env.EXE_SESSION_NAME = fromSessionName;
11147
+ } else {
11148
+ return fromEnv;
11149
+ }
11150
+ }
11136
11151
  }
11137
- const mySession = getMySession();
11138
11152
  if (!mySession) {
11139
11153
  return null;
11140
11154
  }
11141
- const fromSessionName = extractRootExe(mySession);
11142
11155
  let candidate = null;
11143
11156
  try {
11144
11157
  const key = getSessionKey();
@@ -11322,6 +11335,21 @@ function isExeSession(sessionName) {
11322
11335
  }
11323
11336
  function sendIntercom(targetSession) {
11324
11337
  const transport = getTransport();
11338
+ try {
11339
+ const callerScope = resolveExeSession();
11340
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
11341
+ const targetScope = extractRootExe(targetSession);
11342
+ if (targetScope && targetScope !== callerScope) {
11343
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
11344
+ process.stderr.write(
11345
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
11346
+ `
11347
+ );
11348
+ return "failed";
11349
+ }
11350
+ }
11351
+ } catch {
11352
+ }
11325
11353
  if (isExeSession(targetSession)) {
11326
11354
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
11327
11355
  return "skipped_exe";
@@ -7506,15 +7506,28 @@ function getDispatchedBy(sessionKey) {
7506
7506
  }
7507
7507
  }
7508
7508
  function resolveExeSession() {
7509
+ const mySession = getMySession();
7510
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
7509
7511
  if (process.env.EXE_SESSION_NAME) {
7510
7512
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
7511
- if (fromEnv) return fromEnv;
7513
+ if (fromEnv) {
7514
+ if (!mySession) {
7515
+ return fromEnv;
7516
+ }
7517
+ if (fromSessionName && fromEnv !== fromSessionName) {
7518
+ process.stderr.write(
7519
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
7520
+ `
7521
+ );
7522
+ process.env.EXE_SESSION_NAME = fromSessionName;
7523
+ } else {
7524
+ return fromEnv;
7525
+ }
7526
+ }
7512
7527
  }
7513
- const mySession = getMySession();
7514
7528
  if (!mySession) {
7515
7529
  return null;
7516
7530
  }
7517
- const fromSessionName = extractRootExe(mySession);
7518
7531
  let candidate = null;
7519
7532
  try {
7520
7533
  const key = getSessionKey();
@@ -7698,6 +7711,21 @@ function isExeSession(sessionName) {
7698
7711
  }
7699
7712
  function sendIntercom(targetSession) {
7700
7713
  const transport = getTransport();
7714
+ try {
7715
+ const callerScope = resolveExeSession();
7716
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
7717
+ const targetScope = extractRootExe(targetSession);
7718
+ if (targetScope && targetScope !== callerScope) {
7719
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
7720
+ process.stderr.write(
7721
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
7722
+ `
7723
+ );
7724
+ return "failed";
7725
+ }
7726
+ }
7727
+ } catch {
7728
+ }
7701
7729
  if (isExeSession(targetSession)) {
7702
7730
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
7703
7731
  return "skipped_exe";
@@ -8659,15 +8659,28 @@ function getParentExe(sessionKey) {
8659
8659
  }
8660
8660
  }
8661
8661
  function resolveExeSession() {
8662
+ const mySession = getMySession();
8663
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
8662
8664
  if (process.env.EXE_SESSION_NAME) {
8663
8665
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
8664
- if (fromEnv) return fromEnv;
8666
+ if (fromEnv) {
8667
+ if (!mySession) {
8668
+ return fromEnv;
8669
+ }
8670
+ if (fromSessionName && fromEnv !== fromSessionName) {
8671
+ process.stderr.write(
8672
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
8673
+ `
8674
+ );
8675
+ process.env.EXE_SESSION_NAME = fromSessionName;
8676
+ } else {
8677
+ return fromEnv;
8678
+ }
8679
+ }
8665
8680
  }
8666
- const mySession = getMySession();
8667
8681
  if (!mySession) {
8668
8682
  return null;
8669
8683
  }
8670
- const fromSessionName = extractRootExe(mySession);
8671
8684
  let candidate = null;
8672
8685
  try {
8673
8686
  const key = getSessionKey();
@@ -4072,15 +4072,28 @@ function getParentExe(sessionKey) {
4072
4072
  }
4073
4073
  }
4074
4074
  function resolveExeSession() {
4075
+ const mySession = getMySession();
4076
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
4075
4077
  if (process.env.EXE_SESSION_NAME) {
4076
4078
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
4077
- if (fromEnv) return fromEnv;
4079
+ if (fromEnv) {
4080
+ if (!mySession) {
4081
+ return fromEnv;
4082
+ }
4083
+ if (fromSessionName && fromEnv !== fromSessionName) {
4084
+ process.stderr.write(
4085
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
4086
+ `
4087
+ );
4088
+ process.env.EXE_SESSION_NAME = fromSessionName;
4089
+ } else {
4090
+ return fromEnv;
4091
+ }
4092
+ }
4078
4093
  }
4079
- const mySession = getMySession();
4080
4094
  if (!mySession) {
4081
4095
  return null;
4082
4096
  }
4083
- const fromSessionName = extractRootExe(mySession);
4084
4097
  let candidate = null;
4085
4098
  try {
4086
4099
  const key = getSessionKey();
@@ -4043,15 +4043,28 @@ function getParentExe(sessionKey) {
4043
4043
  }
4044
4044
  }
4045
4045
  function resolveExeSession() {
4046
+ const mySession = getMySession();
4047
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
4046
4048
  if (process.env.EXE_SESSION_NAME) {
4047
4049
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
4048
- if (fromEnv) return fromEnv;
4050
+ if (fromEnv) {
4051
+ if (!mySession) {
4052
+ return fromEnv;
4053
+ }
4054
+ if (fromSessionName && fromEnv !== fromSessionName) {
4055
+ process.stderr.write(
4056
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
4057
+ `
4058
+ );
4059
+ process.env.EXE_SESSION_NAME = fromSessionName;
4060
+ } else {
4061
+ return fromEnv;
4062
+ }
4063
+ }
4049
4064
  }
4050
- const mySession = getMySession();
4051
4065
  if (!mySession) {
4052
4066
  return null;
4053
4067
  }
4054
- const fromSessionName = extractRootExe(mySession);
4055
4068
  let candidate = null;
4056
4069
  try {
4057
4070
  const key = getSessionKey();
@@ -6002,15 +6002,28 @@ function getParentExe(sessionKey) {
6002
6002
  }
6003
6003
  }
6004
6004
  function resolveExeSession() {
6005
+ const mySession = getMySession();
6006
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
6005
6007
  if (process.env.EXE_SESSION_NAME) {
6006
6008
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
6007
- if (fromEnv) return fromEnv;
6009
+ if (fromEnv) {
6010
+ if (!mySession) {
6011
+ return fromEnv;
6012
+ }
6013
+ if (fromSessionName && fromEnv !== fromSessionName) {
6014
+ process.stderr.write(
6015
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
6016
+ `
6017
+ );
6018
+ process.env.EXE_SESSION_NAME = fromSessionName;
6019
+ } else {
6020
+ return fromEnv;
6021
+ }
6022
+ }
6008
6023
  }
6009
- const mySession = getMySession();
6010
6024
  if (!mySession) {
6011
6025
  return null;
6012
6026
  }
6013
- const fromSessionName = extractRootExe(mySession);
6014
6027
  let candidate = null;
6015
6028
  try {
6016
6029
  const key = getSessionKey();
package/dist/index.js CHANGED
@@ -7587,15 +7587,28 @@ function getDispatchedBy(sessionKey) {
7587
7587
  }
7588
7588
  }
7589
7589
  function resolveExeSession() {
7590
+ const mySession = getMySession();
7591
+ const fromSessionName = mySession ? extractRootExe(mySession) ?? null : null;
7590
7592
  if (process.env.EXE_SESSION_NAME) {
7591
7593
  const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
7592
- if (fromEnv) return fromEnv;
7594
+ if (fromEnv) {
7595
+ if (!mySession) {
7596
+ return fromEnv;
7597
+ }
7598
+ if (fromSessionName && fromEnv !== fromSessionName) {
7599
+ process.stderr.write(
7600
+ `[tmux-routing] WARN: EXE_SESSION_NAME="${fromEnv}" but tmux says "${fromSessionName}". Trusting tmux, correcting env var.
7601
+ `
7602
+ );
7603
+ process.env.EXE_SESSION_NAME = fromSessionName;
7604
+ } else {
7605
+ return fromEnv;
7606
+ }
7607
+ }
7593
7608
  }
7594
- const mySession = getMySession();
7595
7609
  if (!mySession) {
7596
7610
  return null;
7597
7611
  }
7598
- const fromSessionName = extractRootExe(mySession);
7599
7612
  let candidate = null;
7600
7613
  try {
7601
7614
  const key = getSessionKey();
@@ -7779,6 +7792,21 @@ function isExeSession(sessionName) {
7779
7792
  }
7780
7793
  function sendIntercom(targetSession) {
7781
7794
  const transport = getTransport();
7795
+ try {
7796
+ const callerScope = resolveExeSession();
7797
+ if (callerScope && isExeSession(callerScope) && targetSession.includes("-")) {
7798
+ const targetScope = extractRootExe(targetSession);
7799
+ if (targetScope && targetScope !== callerScope) {
7800
+ logIntercom(`BLOCKED \u2192 ${targetSession} (scope violation: caller=${callerScope}, target=${targetScope})`);
7801
+ process.stderr.write(
7802
+ `[intercom] BLOCKED: cross-session intercom from ${callerScope} to ${targetSession}. Session isolation enforced.
7803
+ `
7804
+ );
7805
+ return "failed";
7806
+ }
7807
+ }
7808
+ } catch {
7809
+ }
7782
7810
  if (isExeSession(targetSession)) {
7783
7811
  logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
7784
7812
  return "skipped_exe";