teamshare-bridge 0.22.8 → 0.22.10

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 (107) hide show
  1. package/dist/bridge/auto-upgrade.d.ts +92 -0
  2. package/dist/bridge/auto-upgrade.js +159 -6
  3. package/dist/bridge/auto-upgrade.js.map +1 -1
  4. package/dist/bridge/daemon-instance.d.ts +17 -0
  5. package/dist/bridge/daemon-instance.js +58 -0
  6. package/dist/bridge/daemon-instance.js.map +1 -1
  7. package/dist/bridge/daemon-support.js +25 -5
  8. package/dist/bridge/daemon-support.js.map +1 -1
  9. package/dist/bridge/daemon.js +254 -83
  10. package/dist/bridge/daemon.js.map +1 -1
  11. package/dist/bridge/doctor.js +42 -5
  12. package/dist/bridge/doctor.js.map +1 -1
  13. package/dist/bridge/index.js +42 -3
  14. package/dist/bridge/index.js.map +1 -1
  15. package/dist/bridge/local-server.d.ts +2 -0
  16. package/dist/bridge/local-server.js +158 -19
  17. package/dist/bridge/local-server.js.map +1 -1
  18. package/dist/bridge/protocol.js +3 -12
  19. package/dist/bridge/protocol.js.map +1 -1
  20. package/dist/bridge/session-relay.d.ts +8 -0
  21. package/dist/bridge/session-relay.js +56 -5
  22. package/dist/bridge/session-relay.js.map +1 -1
  23. package/dist/bridge/upgrade-marker.d.ts +24 -2
  24. package/dist/bridge/upgrade-marker.js +30 -2
  25. package/dist/bridge/upgrade-marker.js.map +1 -1
  26. package/dist/bridge/upgrade-preflight.d.ts +49 -0
  27. package/dist/bridge/upgrade-preflight.js +164 -0
  28. package/dist/bridge/upgrade-preflight.js.map +1 -0
  29. package/dist/cli/commands/board.js +10 -1
  30. package/dist/cli/commands/board.js.map +1 -1
  31. package/dist/cli/commands/browse.js +10 -6
  32. package/dist/cli/commands/browse.js.map +1 -1
  33. package/dist/cli/commands/browser.js +6 -7
  34. package/dist/cli/commands/browser.js.map +1 -1
  35. package/dist/cli/commands/build.js +28 -5
  36. package/dist/cli/commands/build.js.map +1 -1
  37. package/dist/cli/commands/chat.js +10 -1
  38. package/dist/cli/commands/chat.js.map +1 -1
  39. package/dist/cli/commands/cleanup.js +1 -11
  40. package/dist/cli/commands/cleanup.js.map +1 -1
  41. package/dist/cli/commands/connect.js +2 -8
  42. package/dist/cli/commands/connect.js.map +1 -1
  43. package/dist/cli/commands/disconnect.js +4 -10
  44. package/dist/cli/commands/disconnect.js.map +1 -1
  45. package/dist/cli/commands/doc.js +10 -1
  46. package/dist/cli/commands/doc.js.map +1 -1
  47. package/dist/cli/commands/planner.js +10 -1
  48. package/dist/cli/commands/planner.js.map +1 -1
  49. package/dist/cli/commands/research.js +21 -4
  50. package/dist/cli/commands/research.js.map +1 -1
  51. package/dist/cli/commands/run.js +10 -1
  52. package/dist/cli/commands/run.js.map +1 -1
  53. package/dist/lib/brief.js +18 -1
  54. package/dist/lib/brief.js.map +1 -1
  55. package/dist/lib/browser/browse-stealth.js +37 -6
  56. package/dist/lib/browser/browse-stealth.js.map +1 -1
  57. package/dist/lib/browser/profile-guard.d.ts +23 -0
  58. package/dist/lib/browser/profile-guard.js +72 -0
  59. package/dist/lib/browser/profile-guard.js.map +1 -0
  60. package/dist/lib/chat/daemon-reporter.js +8 -1
  61. package/dist/lib/chat/daemon-reporter.js.map +1 -1
  62. package/dist/lib/git/git-discovery.d.ts +23 -4
  63. package/dist/lib/git/git-discovery.js +67 -19
  64. package/dist/lib/git/git-discovery.js.map +1 -1
  65. package/dist/lib/git/git-finalize.js +53 -1
  66. package/dist/lib/git/git-finalize.js.map +1 -1
  67. package/dist/lib/git/index-recovery.js +91 -1
  68. package/dist/lib/git/index-recovery.js.map +1 -1
  69. package/dist/lib/harness/agy-pty.d.ts +1 -1
  70. package/dist/lib/harness/agy-pty.js +20 -4
  71. package/dist/lib/harness/agy-pty.js.map +1 -1
  72. package/dist/lib/harness/spawn.js +98 -24
  73. package/dist/lib/harness/spawn.js.map +1 -1
  74. package/dist/lib/lock.d.ts +6 -0
  75. package/dist/lib/lock.js +108 -15
  76. package/dist/lib/lock.js.map +1 -1
  77. package/dist/lib/orchestrator/handlers/browser.js +9 -8
  78. package/dist/lib/orchestrator/handlers/browser.js.map +1 -1
  79. package/dist/lib/orchestrator/handlers/git.js +88 -6
  80. package/dist/lib/orchestrator/handlers/git.js.map +1 -1
  81. package/dist/lib/orchestrator/worktree.d.ts +10 -0
  82. package/dist/lib/orchestrator/worktree.js +243 -101
  83. package/dist/lib/orchestrator/worktree.js.map +1 -1
  84. package/dist/lib/tail-file.d.ts +4 -0
  85. package/dist/lib/tail-file.js +73 -0
  86. package/dist/lib/tail-file.js.map +1 -0
  87. package/dist/lib/tools/browser-tool.js +13 -2
  88. package/dist/lib/tools/browser-tool.js.map +1 -1
  89. package/dist/lib/wake-claim.d.ts +4 -3
  90. package/dist/lib/wake-claim.js +81 -20
  91. package/dist/lib/wake-claim.js.map +1 -1
  92. package/dist/lib/workspace/bus.d.ts +32 -0
  93. package/dist/lib/workspace/bus.js +48 -1
  94. package/dist/lib/workspace/bus.js.map +1 -1
  95. package/dist/lib/workspace/mirror-lease.js +30 -1
  96. package/dist/lib/workspace/mirror-lease.js.map +1 -1
  97. package/dist/lib/workspace/mirror.js +22 -1
  98. package/dist/lib/workspace/mirror.js.map +1 -1
  99. package/dist/lib/workspace/presence.js +38 -14
  100. package/dist/lib/workspace/presence.js.map +1 -1
  101. package/dist/lib/workspace/repo-lock.d.ts +21 -1
  102. package/dist/lib/workspace/repo-lock.js +146 -21
  103. package/dist/lib/workspace/repo-lock.js.map +1 -1
  104. package/dist/lib/workspace/stop-save.js +10 -0
  105. package/dist/lib/workspace/stop-save.js.map +1 -1
  106. package/package.json +1 -1
  107. package/tools/workspace-arbitration-check.mjs +39 -33
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-support.js","sourceRoot":"","sources":["../../src/bridge/daemon-support.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon-support.js","sourceRoot":"","sources":["../../src/bridge/daemon-support.ts"],"names":[],"mappings":"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"}
@@ -15,12 +15,26 @@ exports.runDaemon = runDaemon;
15
15
  */
16
16
  const node_child_process_1 = require("node:child_process");
17
17
  const node_fs_1 = require("node:fs");
18
+ const tail_file_1 = require("../lib/tail-file");
18
19
  const process_tree_1 = require("../lib/process-tree");
19
20
  const git_runner_1 = require("../lib/git/git-runner");
20
21
  const mirror_1 = require("../lib/workspace/mirror");
21
22
  const stop_save_1 = require("../lib/workspace/stop-save");
22
23
  const bridge_notice_1 = require("../lib/bridge-notice");
23
24
  const wake_outbox_1 = require("./wake-outbox");
25
+ /**
26
+ * Outbox depth that cannot throw. Read for the upgrade diagnostic, so an
27
+ * unreadable queue must degrade to "0" rather than take the daemon's upgrade
28
+ * scheduler down with it.
29
+ */
30
+ const safeOutboxDepth = (agentId) => {
31
+ try {
32
+ return (0, wake_outbox_1.outboxDepth)(agentId);
33
+ }
34
+ catch {
35
+ return 0;
36
+ }
37
+ };
24
38
  const wake_ack_ledger_1 = require("./wake-ack-ledger");
25
39
  /**
26
40
  * Wake types a "Stop work" DISCARDS from the outbox (2026-10).
@@ -315,6 +329,14 @@ async function runDaemon(portOverride) {
315
329
  }
316
330
  /** How long to ask the hub to wait before re-offering a deferred wake. */
317
331
  const DEFER_RETRY_MS = 60_000;
332
+ /**
333
+ * Local attempts a single outbox-lane incarnation gets before its copy is
334
+ * dropped. Matches the hub `pending_wakes` bound so the two queues agree on
335
+ * what "giving up" means. At `LOCK_POLL_MS` that is ~2 minutes of local
336
+ * retries; after that the hub's `retryAfterMs` re-offers the row and the lane
337
+ * starts over with a fresh budget.
338
+ */
339
+ const OUTBOX_MAX_ATTEMPTS = 12;
318
340
  /**
319
341
  * Report every lane this agent still owes a terminal report for, and clear the
320
342
  * local debt (2026-10).
@@ -478,8 +500,15 @@ async function runDaemon(portOverride) {
478
500
  // foreground (only detached `start` used to leave a pid file behind).
479
501
  (0, daemon_support_1.writeDaemonPidFile)();
480
502
  // IMP-950: publish the probe port so shims + CLI tools can find the
481
- // arbiter endpoints without scanning candidate ports.
482
- (0, bus_1.writeRuntimeFile)({ port: boundPort, pid: process.pid, startedAt: new Date().toISOString() });
503
+ // arbiter endpoints without scanning candidate ports. The probe token rides
504
+ // along: every non-public endpoint now requires it (2026-10), and callers
505
+ // already read this file for the port.
506
+ (0, bus_1.writeRuntimeFile)({
507
+ port: boundPort,
508
+ pid: process.pid,
509
+ startedAt: new Date().toISOString(),
510
+ ...((0, local_server_1.getProbeToken)() ? { probeToken: (0, local_server_1.getProbeToken)() } : {}),
511
+ });
483
512
  if (config.agents.length === 0) {
484
513
  (0, daemon_support_1.log)('no agents configured - run: teamshare-agent connect --agent <id> --key ts_...');
485
514
  }
@@ -498,64 +527,87 @@ async function runDaemon(portOverride) {
498
527
  const startedAt = Date.now();
499
528
  const timer = setTimeout(() => {
500
529
  spawnWatchTimers.delete(agentId);
501
- try {
502
- if (sessionRelay.current(agentId))
503
- return; // session came up
504
- const lock = (0, lock_1.readLock)(agentId);
505
- if (lock?.pid) {
530
+ // ASYNC FORENSICS (2026-10).
531
+ //
532
+ // This body used to run synchronously on the DAEMON'S event loop:
533
+ // `readdirSync` over `~/.teamshare/sessions` (every session transcript
534
+ // ever written, plus `launch-*.vbs`), a `statSync` per entry, then
535
+ // `readFileSync` of the ENTIRE newest `spawn-*.log` and
536
+ // `content.split(/\r?\n/)` before taking the last 15 lines. That log is
537
+ // an unbounded append of the child's stdout+stderr, so on a machine that
538
+ // has run a long build it is hundreds of MB - a multi-second freeze in
539
+ // which the 2-minute heartbeat, the 10s outbox drain and the
540
+ // bridge-state push all miss their cadence.
541
+ void (async () => {
542
+ try {
543
+ if (sessionRelay.current(agentId))
544
+ return; // session came up
545
+ const lock = (0, lock_1.readLock)(agentId);
546
+ if (lock?.pid) {
547
+ try {
548
+ process.kill(lock.pid, 0);
549
+ return; // a live session process holds the lock - assume running
550
+ }
551
+ catch {
552
+ /* dead pid - fall through to forensics */
553
+ }
554
+ }
555
+ // No session, no live lock: look for a capture file written by this
556
+ // spawn (hidden-launch creates it only if the chain actually ran).
557
+ let launched = false;
558
+ let captureInfo = 'no capture file - the hidden launcher never ran (Windows Script Host/wscript.exe may be disabled or blocked by antivirus)';
559
+ const dir = (0, node_path_1.join)((0, node_os_1.homedir)(), '.teamshare', 'sessions');
560
+ let names = [];
506
561
  try {
507
- process.kill(lock.pid, 0);
508
- return; // a live session process holds the lock - assume running
562
+ names = await node_fs_1.promises.readdir(dir);
509
563
  }
510
564
  catch {
511
- /* dead pid - fall through to forensics */
565
+ names = []; // folder never created, or cleaned up
512
566
  }
513
- }
514
- // No session, no live lock: look for a capture file written by this
515
- // spawn (hidden-launch creates it only if the chain actually ran).
516
- let launched = false;
517
- let captureInfo = 'no capture file - the hidden launcher never ran (Windows Script Host/wscript.exe may be disabled or blocked by antivirus)';
518
- const dir = (0, node_path_1.join)((0, node_os_1.homedir)(), '.teamshare', 'sessions');
519
- let newest = null;
520
- for (const f of (0, node_fs_1.readdirSync)(dir)) {
521
- if (!f.startsWith('spawn-') || !f.endsWith('.log'))
522
- continue;
523
- const st = (0, node_fs_1.statSync)((0, node_path_1.join)(dir, f), { throwIfNoEntry: false });
524
- if (!st)
525
- continue;
526
- if (st.mtimeMs >= startedAt - 2_000 &&
527
- (!newest || st.mtimeMs > newest.mtime)) {
528
- newest = { file: f, mtime: st.mtimeMs };
567
+ const stamped = await Promise.all(names
568
+ .filter((f) => f.startsWith('spawn-') && f.endsWith('.log'))
569
+ .map(async (f) => {
570
+ try {
571
+ const st = await node_fs_1.promises.stat((0, node_path_1.join)(dir, f));
572
+ return { f, mtime: st.mtimeMs };
573
+ }
574
+ catch {
575
+ return null;
576
+ }
577
+ }));
578
+ let newest = null;
579
+ for (const entry of stamped) {
580
+ if (!entry)
581
+ continue;
582
+ if (entry.mtime >= startedAt - 2_000 && (!newest || entry.mtime > newest.mtime)) {
583
+ newest = { file: entry.f, mtime: entry.mtime };
584
+ }
585
+ }
586
+ if (newest) {
587
+ launched = true;
588
+ // Tail-read: bounded no matter how much the child printed.
589
+ const tail = await (0, tail_file_1.readTailLines)((0, node_path_1.join)(dir, newest.file), 15);
590
+ captureInfo = tail
591
+ ? `capture ${newest.file} tail:\n${tail}`
592
+ : `capture ${newest.file} exists but is empty - the CLI exited before logging anything (native-module load failure?)`;
529
593
  }
594
+ (0, daemon_support_1.log)(`agent ${agentId}: spawn watch - no session started ${Math.round((Date.now() - startedAt) / 1000)}s after ${wakeType} wake`);
595
+ (0, diagnostics_1.reportDiagnosticSafe)({
596
+ kind: 'spawn_failure',
597
+ severity: 'error',
598
+ agentId,
599
+ message: `Session never started after a ${wakeType} wake (${launched ? 'CLI exited before session:start' : 'hidden launcher never ran'})`,
600
+ errorCode: launched
601
+ ? 'SESSION_PREMATURE_EXIT'
602
+ : 'SESSION_NEVER_LAUNCHED',
603
+ context: { wakeType, capture: captureInfo.slice(0, 4_000) },
604
+ includeDoctor: true,
605
+ });
530
606
  }
531
- if (newest) {
532
- launched = true;
533
- const content = (0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, newest.file), 'utf8');
534
- const tail = content
535
- .split(/\r?\n/)
536
- .filter(Boolean)
537
- .slice(-15)
538
- .join('\n');
539
- captureInfo = tail
540
- ? `capture ${newest.file} tail:\n${tail}`
541
- : `capture ${newest.file} exists but is empty - the CLI exited before logging anything (native-module load failure?)`;
607
+ catch (err) {
608
+ (0, daemon_support_1.log)(`agent ${agentId}: spawn watch failed: ${(0, config_1.msg)(err)}`);
542
609
  }
543
- (0, daemon_support_1.log)(`agent ${agentId}: spawn watch - no session started ${Math.round((Date.now() - startedAt) / 1000)}s after ${wakeType} wake`);
544
- (0, diagnostics_1.reportDiagnosticSafe)({
545
- kind: 'spawn_failure',
546
- severity: 'error',
547
- agentId,
548
- message: `Session never started after a ${wakeType} wake (${launched ? 'CLI exited before session:start' : 'hidden launcher never ran'})`,
549
- errorCode: launched
550
- ? 'SESSION_PREMATURE_EXIT'
551
- : 'SESSION_NEVER_LAUNCHED',
552
- context: { wakeType, capture: captureInfo.slice(0, 4_000) },
553
- includeDoctor: true,
554
- });
555
- }
556
- catch (err) {
557
- (0, daemon_support_1.log)(`agent ${agentId}: spawn watch failed: ${(0, config_1.msg)(err)}`);
558
- }
610
+ })();
559
611
  }, 20_000);
560
612
  timer.unref();
561
613
  spawnWatchTimers.set(agentId, timer);
@@ -764,6 +816,8 @@ async function runDaemon(portOverride) {
764
816
  const config = getConfig;
765
817
  const agentTimers = [];
766
818
  let timersCreated = false;
819
+ /** At most one pending staggered first-beat; see the `connect` handler. */
820
+ let firstBeatTimer = null;
767
821
  /** Consecutive 401 "Invalid API key" heartbeats before we stop retrying. */
768
822
  let authFailures = 0;
769
823
  const isAuthError = (err) => err instanceof api_1.ApiError
@@ -913,10 +967,23 @@ async function runDaemon(portOverride) {
913
967
  // is safe. Later beats ride the 2-min heartbeat + 5-min push cadence.
914
968
  const seq = (0, daemon_support_1.nextAgentLoopSeq)();
915
969
  const firstBeatMs = Math.round(daemon_support_1.HEARTBEAT_MS * (0.25 + 0.5 * ((seq % 6) / 6)));
916
- agentTimers.push(setTimeout(() => {
970
+ // ONE pending first-beat at a time. This block runs on EVERY `connect`,
971
+ // and a flapping socket used to push another `setTimeout` each time: the
972
+ // array grew for the life of the loop AND every stale timer still fired
973
+ // its own heartbeat + pushState, so a reconnect storm turned into a burst
974
+ // of duplicate beats instead of one.
975
+ if (firstBeatTimer) {
976
+ clearTimeout(firstBeatTimer);
977
+ const staleIdx = agentTimers.indexOf(firstBeatTimer);
978
+ if (staleIdx >= 0)
979
+ agentTimers.splice(staleIdx, 1);
980
+ }
981
+ firstBeatTimer = setTimeout(() => {
982
+ firstBeatTimer = null;
917
983
  heartbeat();
918
984
  pushState();
919
- }, firstBeatMs));
985
+ }, firstBeatMs);
986
+ agentTimers.push(firstBeatTimer);
920
987
  // Only create persistent intervals on the first connect — reconnects
921
988
  // reuse the existing timers (they survive socket disconnects).
922
989
  if (!timersCreated) {
@@ -1157,7 +1224,34 @@ async function runDaemon(portOverride) {
1157
1224
  orchestratorClient,
1158
1225
  });
1159
1226
  reportWakeOutcome(agent.agentId, socket, event, outcome);
1160
- })().catch((err) => (0, daemon_support_1.log)(`agent ${agent.agentId}: wake failed: ${(0, config_1.msg)(err)}`));
1227
+ })().catch((err) => {
1228
+ (0, daemon_support_1.log)(`agent ${agent.agentId}: wake failed: ${(0, config_1.msg)(err)}`);
1229
+ // The receipt (`wake.received` / noteAck) was already emitted before
1230
+ // `handleWake` ran, so without this the hub row sat `acknowledged`
1231
+ // forever with no `wake.settled` and no `wake.defer` - the human saw
1232
+ // "Wake received" and no work, with nothing in the run history to
1233
+ // explain it. A deferred report is the negative ack that lets the hub's
1234
+ // retry clock take over, and a diagnostic records WHY.
1235
+ try {
1236
+ (0, diagnostics_1.reportDiagnosticSafe)({
1237
+ kind: 'wake_failure',
1238
+ severity: 'error',
1239
+ agentId: agent.agentId,
1240
+ errorCode: 'WAKE_HANDLER_THREW',
1241
+ message: `${String(event.type)}: ${(0, config_1.msg)(err)}`,
1242
+ includeDoctor: true,
1243
+ });
1244
+ }
1245
+ catch {
1246
+ /* reporting must never mask the wake failure */
1247
+ }
1248
+ try {
1249
+ reportWakeOutcome(agent.agentId, socket, event, 'deferred');
1250
+ }
1251
+ catch {
1252
+ /* socket already gone - the hub's reclaim sweep is the backstop */
1253
+ }
1254
+ });
1161
1255
  });
1162
1256
  sockets.push(socket);
1163
1257
  // 2026-09: restore this agent's queued wakes from disk instead of wiping
@@ -1359,6 +1453,9 @@ async function runDaemon(portOverride) {
1359
1453
  const res = await fetch(`${apiBase}/agents/${agentId}/keys/rotate`, {
1360
1454
  method: 'POST',
1361
1455
  headers: { Authorization: `Bearer ${h.apiKey}` },
1456
+ // Node's fetch has NO default timeout, so one hung request stalled
1457
+ // this `for` loop and every agent queued behind it never rotated.
1458
+ signal: AbortSignal.timeout(30_000),
1362
1459
  });
1363
1460
  if (!res.ok)
1364
1461
  continue;
@@ -1427,7 +1524,33 @@ async function runDaemon(portOverride) {
1427
1524
  (0, daemon_support_1.log)(`agent ${agentId}: outbox drain paused after a lane took the lock`);
1428
1525
  return;
1429
1526
  }
1430
- const outcome = await (0, wake_handler_1.handleWake)(api_1.TeamshareApi.forAgent(apiBase, agent), agentId, agent.apiKey, lane.event, getConfig(), { wakeQueue, settings, recentSpawns, orchestratorClient });
1527
+ let outcome;
1528
+ try {
1529
+ outcome = await (0, wake_handler_1.handleWake)(api_1.TeamshareApi.forAgent(apiBase, agent), agentId, agent.apiKey, lane.event, getConfig(), { wakeQueue, settings, recentSpawns, orchestratorClient });
1530
+ }
1531
+ catch (err) {
1532
+ // Per-lane, not per-tick: a throw anywhere in the loop used to be
1533
+ // caught only by the IIFE below, which logged a line and never
1534
+ // called `reportWakeOutcome` - so the row stayed `acknowledged` on
1535
+ // the hub AND every remaining lane for this agent was abandoned for
1536
+ // the tick. Convert it to the negative ack the rest of this body
1537
+ // already knows how to send.
1538
+ (0, daemon_support_1.log)(`agent ${agentId}: outbox lane ${lane.lane} threw: ${(0, config_1.msg)(err)}`);
1539
+ try {
1540
+ (0, diagnostics_1.reportDiagnosticSafe)({
1541
+ kind: 'wake_failure',
1542
+ severity: 'error',
1543
+ agentId,
1544
+ errorCode: 'WAKE_HANDLER_THREW',
1545
+ message: `${String(lane.event.type)}: ${(0, config_1.msg)(err)}`,
1546
+ includeDoctor: true,
1547
+ });
1548
+ }
1549
+ catch {
1550
+ /* reporting must never mask the failure */
1551
+ }
1552
+ outcome = 'deferred';
1553
+ }
1431
1554
  // Anything that is NOT finished with the lane stays queued. That covers
1432
1555
  // 'queued', 'deferred' and 'blocked' - the three outcomes that mean
1433
1556
  // "ask again later" - plus a thrown error handled below.
@@ -1465,48 +1588,87 @@ async function runDaemon(portOverride) {
1465
1588
  // report for a deliberately failed 'blocked') is what stops the row
1466
1589
  // sitting `acknowledged` on the hub while the outbox holds it.
1467
1590
  reportWakeOutcome(agentId, h.socket, lane.event, outcome);
1591
+ // Bound the LOCAL retry (2026-10).
1592
+ //
1593
+ // `noteAttempt` has been exported since the outbox was written and
1594
+ // had ZERO call sites, so `OutboxLane.attempts` was persisted on
1595
+ // every enqueue and never incremented: a lane that could not make
1596
+ // progress was retried every LOCK_POLL_MS forever, each tick costing
1597
+ // an authenticated `GET /agents/:id/settings` on top of the full
1598
+ // `handleWake` pass. This is the same "wired but zero readers"
1599
+ // failure `AGENTS.md` records for Jira's `markPulled`/`touchSynced`.
1600
+ //
1601
+ // Dropping the local copy is safe BECAUSE the report above sent
1602
+ // `retryAfterMs`: the hub re-offers the row in 60 s, which enqueues
1603
+ // a FRESH lane with `attempts` back at 0. So the hub - not this file
1604
+ // - is the retry clock, and the cap only stops one incarnation of a
1605
+ // stuck lane from spinning.
1606
+ const kept = (0, wake_outbox_1.noteAttempt)(agentId, lane.lane, OUTBOX_MAX_ATTEMPTS);
1607
+ if (!kept) {
1608
+ (0, daemon_support_1.log)(`agent ${agentId}: outbox lane ${lane.lane} gave up after ` +
1609
+ `${OUTBOX_MAX_ATTEMPTS} attempts (${outcome}) - local copy dropped; ` +
1610
+ `the hub's PendingWake row (retryAfterMs) is the recovery path`);
1611
+ }
1468
1612
  }
1469
1613
  }
1470
1614
  })().catch((err) => {
1615
+ // Only `freshSettings` (above the loop) can reject now - each lane's
1616
+ // `handleWake` is caught per-lane. Without a report here the settings
1617
+ // fetch failing left the row `acknowledged` indefinitely.
1471
1618
  (0, daemon_support_1.log)(`agent ${agentId}: outbox drain failed: ${(0, config_1.msg)(err)}`);
1619
+ try {
1620
+ (0, diagnostics_1.reportDiagnosticSafe)({
1621
+ kind: 'wake_failure',
1622
+ severity: 'error',
1623
+ agentId,
1624
+ errorCode: 'OUTBOX_DRAIN_THREW',
1625
+ message: (0, config_1.msg)(err),
1626
+ });
1627
+ }
1628
+ catch {
1629
+ /* best-effort */
1630
+ }
1472
1631
  });
1473
1632
  }
1474
1633
  }, lock_1.LOCK_POLL_MS);
1475
1634
  timers.push(flushInterval);
1476
- timers.push(flushInterval);
1477
1635
  // ── Silent auto-upgrade (2026-09) ──────────────────────────────────────
1478
1636
  // The daemon installs the newest published `teamshare-bridge` on its own
1479
- // once THIS machine has been fully idle: no session lock, no live session,
1480
- // no queued/folder-waiting wakes and nothing started in the last few
1481
- // minutes. Opt out with `teamshare-bridge auto-upgrade off` (config
1482
- // autoUpgrade).
1637
+ // once THIS machine is not EXECUTING anything. Opt out with
1638
+ // `teamshare-bridge auto-upgrade off` (config autoUpgrade).
1483
1639
  //
1484
- // WAKE_QUIET only has to cover the gap between a wake arriving and its
1485
- // session taking the agent lock (hidden launch + node boot + settings
1486
- // fetch - seconds). After that the lock/queue/session checks take over,
1487
- // so the 10-min continuous-idle window in idleVerdict stays the real gate.
1488
- const WAKE_QUIET_MS = 2 * 60_000;
1640
+ // WHAT COUNTS AS "BUSY" lives in `upgradeBlockingReason` (auto-upgrade.ts),
1641
+ // not here: it is a pure exported function so the queued-vs-executing rule
1642
+ // can be regression-tested instead of trusted. This loop only collects the
1643
+ // observations.
1489
1644
  const machineBusy = () => {
1645
+ const now = Date.now();
1490
1646
  for (const agent of (0, config_1.loadConfig)().agents) {
1491
- if ((0, lock_1.isLockBusy)(agent.agentId)) {
1492
- return `agent ${agent.agentId} holds a session lock`;
1493
- }
1494
- if (sessionRelay.current(agent.agentId)) {
1495
- return `agent ${agent.agentId} has a live session`;
1496
- }
1497
- if ((0, wake_outbox_1.outboxDepth)(agent.agentId) > 0) {
1498
- return `agent ${agent.agentId} has queued wakes`;
1499
- }
1500
- const lastWake = lastWakeByAgent.get(agent.agentId);
1501
- if (lastWake) {
1502
- const ago = Date.now() - Date.parse(lastWake);
1503
- if (Number.isFinite(ago) && ago < WAKE_QUIET_MS) {
1504
- return `a wake landed ${Math.round(ago / 1000)}s ago`;
1505
- }
1506
- }
1647
+ const reason = (0, auto_upgrade_1.upgradeBlockingReason)({
1648
+ agentId: agent.agentId,
1649
+ lockBusy: (0, lock_1.isLockBusy)(agent.agentId),
1650
+ liveSession: sessionRelay.current(agent.agentId) !== undefined &&
1651
+ sessionRelay.current(agent.agentId) !== null,
1652
+ lastWakeAt: lastWakeByAgent.get(agent.agentId) ?? null,
1653
+ queuedWakes: safeOutboxDepth(agent.agentId),
1654
+ now,
1655
+ });
1656
+ if (reason)
1657
+ return reason;
1507
1658
  }
1508
1659
  return null;
1509
1660
  };
1661
+ /**
1662
+ * Total durable queued wakes across every agent. Diagnostics only - it is
1663
+ * deliberately NOT part of the upgrade gate (see `upgradeBlockingReason`).
1664
+ */
1665
+ const queuedWakes = () => {
1666
+ let total = 0;
1667
+ for (const agent of (0, config_1.loadConfig)().agents) {
1668
+ total += safeOutboxDepth(agent.agentId);
1669
+ }
1670
+ return total;
1671
+ };
1510
1672
  let stopAutoUpgrade = () => { };
1511
1673
  stopAutoUpgrade = (0, auto_upgrade_1.startAutoUpgrade)({
1512
1674
  log: daemon_support_1.log,
@@ -1515,6 +1677,9 @@ async function runDaemon(portOverride) {
1515
1677
  version: (0, version_check_1.currentVersion)(),
1516
1678
  port: boundPort,
1517
1679
  shutdown: () => shutdown(),
1680
+ // Reported once per state change, not per 30s sample, so the hub shows
1681
+ // "update pending, waiting for idle" instead of a repeating trickle.
1682
+ describeQueue: queuedWakes,
1518
1683
  report: async (severity, message, context) => {
1519
1684
  await (0, diagnostics_1.reportDiagnostic)({
1520
1685
  kind: 'auto_upgrade',
@@ -1546,6 +1711,12 @@ async function runDaemon(portOverride) {
1546
1711
  catch { /* best-effort */ }
1547
1712
  for (const t of timers)
1548
1713
  clearInterval(t);
1714
+ // Pending spawn-watchdog timers. They are `.unref()`'d so they never hold
1715
+ // the process open, but they are created outside `timers` (one per agent,
1716
+ // rescheduled on every spawn) and so were never cleared here.
1717
+ for (const t of spawnWatchTimers.values())
1718
+ clearTimeout(t);
1719
+ spawnWatchTimers.clear();
1549
1720
  // Graceful shutdown SETTLES what this boot owes (2026-10). Sockets are still
1550
1721
  // open here, so the reports land — and settling is honest on a clean stop,
1551
1722
  // unlike the crash path, which deliberately reports nothing so the hub can