@bridge4dev/runner 0.36.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const RUNNER_VERSION = "0.36.0";
1
+ export declare const RUNNER_VERSION = "0.38.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Kept in sync with package.json by the release script (manual for now).
2
- export const RUNNER_VERSION = '0.36.0';
2
+ export const RUNNER_VERSION = '0.38.0';
3
3
  //# sourceMappingURL=version.js.map
@@ -1,4 +1,32 @@
1
1
  import { type GatewayFrame, type RunnerFrame } from './protocol.js';
2
+ /**
3
+ * Mirror of `RUNNER_LIVENESS_*` in `@devbridge/shared` — the DevBridge side is the
4
+ * source of truth, exactly like `protocol.ts` mirrors the API's wire types.
5
+ * Copied rather than imported because this package is published to npm on its own
6
+ * (see the note in `recipe-schema.ts`).
7
+ *
8
+ * No inbound traffic for this long means the path is half-dead even though the
9
+ * socket still looks OPEN (QA-96 F16). The threshold has to stay comfortably
10
+ * BELOW the gateway's own budget (`RUNNER_GATEWAY_BUDGET_MS`, 60 s): a re-connect
11
+ * that lands before the gateway gives up is free — it replaces the old socket and
12
+ * the machine never leaves ONLINE — while one that lands after costs the user a
13
+ * «server is offline» banner over a working machine (QA-162 F2).
14
+ *
15
+ * It used to say «the gateway pings every 30s» and wait 90 s. The gateway has
16
+ * pinged every 15 s since devreport #117, so that 90 s had quietly become six
17
+ * missed pings instead of the three it was written for, and the runner sat blind
18
+ * for 90–120 s on every drop. Both ends now read one set of numbers.
19
+ */
20
+ export declare const LIVENESS_TIMEOUT_MS = 35000;
21
+ export declare const LIVENESS_CHECK_MS = 5000;
22
+ /** Kept in step with `RUNNER_GATEWAY_BUDGET_MS`; asserted by `ws-liveness.test.ts`. */
23
+ export declare const GATEWAY_BUDGET_MS = 60000;
24
+ /**
25
+ * Worst-case cost of acting on the threshold: the check granularity, the first
26
+ * backoff step with its jitter, and a TLS+upgrade handshake. The invariant test
27
+ * uses it, because «the runner re-dials first» is only true with this included.
28
+ */
29
+ export declare const RECONNECT_COST_MS: number;
2
30
  export interface WsClientEvents {
3
31
  frame: (frame: GatewayFrame) => void;
4
32
  open: () => void;
package/dist/ws-client.js CHANGED
@@ -9,10 +9,34 @@ import { RUNNER_VERSION } from './version.js';
9
9
  const BACKOFF_BASE_MS = 1_000;
10
10
  const BACKOFF_MAX_MS = 60_000;
11
11
  const REPLACED_COOLDOWN_MS = 60_000;
12
- // The gateway pings every 30s; no inbound traffic for 90s means the path is
13
- // half-dead even though the socket looks OPEN (QA-96 F16).
14
- const LIVENESS_TIMEOUT_MS = 90_000;
15
- const LIVENESS_CHECK_MS = 30_000;
12
+ /**
13
+ * Mirror of `RUNNER_LIVENESS_*` in `@devbridge/shared` — the DevBridge side is the
14
+ * source of truth, exactly like `protocol.ts` mirrors the API's wire types.
15
+ * Copied rather than imported because this package is published to npm on its own
16
+ * (see the note in `recipe-schema.ts`).
17
+ *
18
+ * No inbound traffic for this long means the path is half-dead even though the
19
+ * socket still looks OPEN (QA-96 F16). The threshold has to stay comfortably
20
+ * BELOW the gateway's own budget (`RUNNER_GATEWAY_BUDGET_MS`, 60 s): a re-connect
21
+ * that lands before the gateway gives up is free — it replaces the old socket and
22
+ * the machine never leaves ONLINE — while one that lands after costs the user a
23
+ * «server is offline» banner over a working machine (QA-162 F2).
24
+ *
25
+ * It used to say «the gateway pings every 30s» and wait 90 s. The gateway has
26
+ * pinged every 15 s since devreport #117, so that 90 s had quietly become six
27
+ * missed pings instead of the three it was written for, and the runner sat blind
28
+ * for 90–120 s on every drop. Both ends now read one set of numbers.
29
+ */
30
+ export const LIVENESS_TIMEOUT_MS = 35_000;
31
+ export const LIVENESS_CHECK_MS = 5_000;
32
+ /** Kept in step with `RUNNER_GATEWAY_BUDGET_MS`; asserted by `ws-liveness.test.ts`. */
33
+ export const GATEWAY_BUDGET_MS = 60_000;
34
+ /**
35
+ * Worst-case cost of acting on the threshold: the check granularity, the first
36
+ * backoff step with its jitter, and a TLS+upgrade handshake. The invariant test
37
+ * uses it, because «the runner re-dials first» is only true with this included.
38
+ */
39
+ export const RECONNECT_COST_MS = LIVENESS_CHECK_MS + BACKOFF_BASE_MS + 1_000 + 2_000;
16
40
  // Repeated HTTP 401/403 on the upgrade = bad token; slow way down.
17
41
  const AUTH_FAILURE_THRESHOLD = 5;
18
42
  const AUTH_FAILURE_COOLDOWN_MS = 10 * 60_000;
@@ -86,12 +110,17 @@ export class RunnerWsClient {
86
110
  if (this.stopped)
87
111
  return;
88
112
  log.info('ws: connecting', { url: this.wsUrl, attempt: this.attempts + 1 });
113
+ const dialedAt = Date.now();
89
114
  const socket = new WebSocket(this.wsUrl, {
90
115
  headers: { Authorization: `Bearer ${this.token}` },
91
116
  handshakeTimeout: 15_000,
92
117
  });
93
118
  this.socket = socket;
94
119
  socket.on('open', () => {
120
+ // Success used to be the only outcome that logged NOTHING, so «connected»
121
+ // and «hung mid-handshake» read identically in the journal — which is
122
+ // exactly where an hour went during QA-162. One line ends that.
123
+ log.info('ws: connected', { attempts: this.attempts + 1, elapsedMs: Date.now() - dialedAt });
95
124
  this.attempts = 0;
96
125
  this.authFailures = 0;
97
126
  this.lastInboundAt = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge4dev/runner",
3
- "version": "0.36.0",
3
+ "version": "0.38.0",
4
4
  "description": "DevBridge dev runner — connects a dev server to DevBridge and runs agent sessions (Claude Code / Codex)",
5
5
  "homepage": "https://bridge4.dev",
6
6
  "license": "MIT",