@tekyzinc/gsd-t 3.29.11 → 4.0.14

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 (114) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/bin/gsd-t-parallel.cjs +64 -13
  3. package/bin/gsd-t.js +48 -376
  4. package/bin/journey-coverage.cjs +6 -3
  5. package/bin/parallel-cli.cjs +13 -1
  6. package/commands/gsd-t-complete-milestone.md +6 -12
  7. package/commands/gsd-t-debug.md +47 -533
  8. package/commands/gsd-t-design-decompose.md +24 -497
  9. package/commands/gsd-t-doc-ripple.md +23 -139
  10. package/commands/gsd-t-execute.md +41 -958
  11. package/commands/gsd-t-feature.md +2 -6
  12. package/commands/gsd-t-gap-analysis.md +3 -6
  13. package/commands/gsd-t-help.md +2 -4
  14. package/commands/gsd-t-impact.md +26 -295
  15. package/commands/gsd-t-init-scan-setup.md +7 -7
  16. package/commands/gsd-t-integrate.md +44 -369
  17. package/commands/gsd-t-milestone.md +25 -124
  18. package/commands/gsd-t-partition.md +28 -539
  19. package/commands/gsd-t-plan.md +26 -472
  20. package/commands/gsd-t-prd.md +25 -311
  21. package/commands/gsd-t-quick.md +1 -1
  22. package/commands/gsd-t-resume.md +0 -33
  23. package/commands/gsd-t-scan.md +45 -652
  24. package/commands/gsd-t-verify.md +52 -569
  25. package/commands/gsd-t-wave.md +41 -430
  26. package/package.json +1 -1
  27. package/scripts/gsd-t-calibration-hook.js +3 -1
  28. package/scripts/hooks/pre-commit-journey-coverage +0 -2
  29. package/scripts/hooks/pre-commit-playwright-gate +0 -2
  30. package/templates/CLAUDE-global.md +44 -173
  31. package/templates/CLAUDE-project.md +118 -104
  32. package/templates/prompts/design-verify-subagent.md +3 -0
  33. package/templates/prompts/qa-subagent.md +3 -0
  34. package/templates/prompts/red-team-subagent.md +5 -2
  35. package/templates/workflows/_lib.js +176 -0
  36. package/templates/workflows/gsd-t-debug.workflow.js +86 -0
  37. package/templates/workflows/gsd-t-execute.workflow.js +206 -0
  38. package/templates/workflows/gsd-t-integrate.workflow.js +71 -0
  39. package/templates/workflows/gsd-t-phase.workflow.js +94 -0
  40. package/templates/workflows/gsd-t-quick.workflow.js +72 -0
  41. package/templates/workflows/gsd-t-scan.workflow.js +711 -0
  42. package/templates/workflows/gsd-t-verify.workflow.js +348 -0
  43. package/templates/workflows/gsd-t-wave.workflow.js +43 -0
  44. package/bin/check-headless-sessions.js +0 -140
  45. package/bin/context-budget-audit.cjs +0 -447
  46. package/bin/context-meter-config.cjs +0 -101
  47. package/bin/context-meter-config.test.cjs +0 -101
  48. package/bin/event-stream.cjs +0 -205
  49. package/bin/gsd-t-benchmark-orchestrator.js +0 -437
  50. package/bin/gsd-t-capture-lint.cjs +0 -440
  51. package/bin/gsd-t-economics.cjs +0 -315
  52. package/bin/gsd-t-in-session-usage.cjs +0 -213
  53. package/bin/gsd-t-orchestrator-config.cjs +0 -161
  54. package/bin/gsd-t-orchestrator-queue.cjs +0 -180
  55. package/bin/gsd-t-orchestrator-recover.cjs +0 -231
  56. package/bin/gsd-t-orchestrator-worker.cjs +0 -219
  57. package/bin/gsd-t-orchestrator.js +0 -535
  58. package/bin/gsd-t-parallel-probe.cjs +0 -132
  59. package/bin/gsd-t-ratelimit-probe-worker.cjs +0 -237
  60. package/bin/gsd-t-ratelimit-probe.cjs +0 -648
  61. package/bin/gsd-t-report-tokens.cjs +0 -549
  62. package/bin/gsd-t-stream-feed-client.cjs +0 -151
  63. package/bin/gsd-t-token-backfill.cjs +0 -366
  64. package/bin/gsd-t-token-capture.cjs +0 -321
  65. package/bin/gsd-t-token-dashboard.cjs +0 -353
  66. package/bin/gsd-t-token-regenerate-log.cjs +0 -129
  67. package/bin/gsd-t-tool-attribution.cjs +0 -377
  68. package/bin/gsd-t-tool-cost.cjs +0 -195
  69. package/bin/gsd-t-transcript-tee.cjs +0 -246
  70. package/bin/gsd-t-unattended-heartbeat.cjs +0 -188
  71. package/bin/gsd-t-unattended-platform.cjs +0 -551
  72. package/bin/gsd-t-unattended-platform.js +0 -381
  73. package/bin/gsd-t-unattended-safety.cjs +0 -773
  74. package/bin/gsd-t-unattended-safety.js +0 -788
  75. package/bin/gsd-t-unattended.cjs +0 -2109
  76. package/bin/gsd-t-unattended.js +0 -1367
  77. package/bin/gsd-t-worker-dispatch.cjs +0 -211
  78. package/bin/handoff-lock.cjs +0 -249
  79. package/bin/handoff-lock.js +0 -249
  80. package/bin/headless-auto-spawn.cjs +0 -711
  81. package/bin/headless-auto-spawn.js +0 -373
  82. package/bin/headless-exit-codes.cjs +0 -67
  83. package/bin/live-activity-report.cjs +0 -615
  84. package/bin/log-tail.cjs +0 -81
  85. package/bin/m44-proof-measure.cjs +0 -285
  86. package/bin/m46-iter-proof.cjs +0 -149
  87. package/bin/m46-worker-proof.cjs +0 -201
  88. package/bin/m55-substrate-proof.cjs +0 -134
  89. package/bin/metrics-rollup.js +0 -200
  90. package/bin/model-windows.cjs +0 -99
  91. package/bin/model-windows.test.cjs +0 -75
  92. package/bin/parallelism-report.cjs +0 -535
  93. package/bin/runway-estimator.cjs +0 -242
  94. package/bin/spawn-plan-derive.cjs +0 -163
  95. package/bin/spawn-plan-status-updater.cjs +0 -292
  96. package/bin/spawn-plan-writer.cjs +0 -204
  97. package/bin/supervisor-pid-fingerprint.cjs +0 -126
  98. package/bin/token-budget.cjs +0 -265
  99. package/bin/unattended-watch-format.cjs +0 -178
  100. package/bin/watch-progress.js +0 -155
  101. package/commands/gsd-t-unattended-stop.md +0 -85
  102. package/commands/gsd-t-unattended-watch.md +0 -465
  103. package/commands/gsd-t-unattended.md +0 -476
  104. package/commands/gsd-t-visualize.md +0 -116
  105. package/scripts/gsd-t-context-meter.e2e.test.js +0 -364
  106. package/scripts/gsd-t-context-meter.js +0 -341
  107. package/scripts/gsd-t-context-meter.test.js +0 -471
  108. package/scripts/gsd-t-dashboard-server.js +0 -1203
  109. package/scripts/gsd-t-post-commit-spawn-plan.sh +0 -86
  110. package/scripts/gsd-t-transcript.html +0 -1821
  111. package/scripts/hooks/gsd-t-conversation-capture.js +0 -439
  112. package/scripts/hooks/gsd-t-in-session-usage-hook.js +0 -84
  113. package/scripts/spawn-plan-fmt-tokens.cjs +0 -80
  114. package/templates/hooks/post-commit-spawn-plan.sh +0 -85
@@ -1,246 +0,0 @@
1
- 'use strict';
2
- /**
3
- * GSD-T Transcript Tee (M42 D1)
4
- *
5
- * Captures raw stream-json frames from every unattended spawn to
6
- * `.gsd-t/transcripts/{spawn-id}.ndjson` + maintains a registry at
7
- * `.gsd-t/transcripts/.index.json` used by the dashboard sidebar.
8
- *
9
- * Zero external deps. Append-only. Does not parse the frames — that's the
10
- * renderer's job. One frame per line; lines that fail JSON parse are still
11
- * tee'd so nothing is silently dropped.
12
- *
13
- * Contracts:
14
- * - .gsd-t/contracts/stream-json-sink-contract.md v1.1.0 (frame shape)
15
- */
16
-
17
- const fs = require('fs');
18
- const path = require('path');
19
- const crypto = require('crypto');
20
-
21
- const TRANSCRIPTS_DIRNAME = path.join('.gsd-t', 'transcripts');
22
- const INDEX_FILENAME = '.index.json';
23
-
24
- function _transcriptsDir(projectDir) {
25
- return path.join(projectDir || '.', TRANSCRIPTS_DIRNAME);
26
- }
27
-
28
- function _indexPath(projectDir) {
29
- return path.join(_transcriptsDir(projectDir), INDEX_FILENAME);
30
- }
31
-
32
- function _ensureDir(p) {
33
- if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true });
34
- }
35
-
36
- /**
37
- * Allocate a hierarchical spawn-id. Shape: `{parent-prefix}-{short}` where
38
- * `short` is an 8-char hex from a random UUID. Root spawns get no prefix.
39
- *
40
- * @param {object} [opts]
41
- * @param {string|null} [opts.parentId]
42
- * @returns {string}
43
- */
44
- function allocateSpawnId(opts) {
45
- const parentId = opts && opts.parentId ? String(opts.parentId) : null;
46
- const short = crypto.randomBytes(4).toString('hex');
47
- return parentId ? `${parentId}.${short}` : `s-${short}`;
48
- }
49
-
50
- function _readIndex(projectDir) {
51
- const p = _indexPath(projectDir);
52
- if (!fs.existsSync(p)) return { spawns: [] };
53
- try {
54
- const raw = fs.readFileSync(p, 'utf8');
55
- const parsed = JSON.parse(raw);
56
- if (!parsed || typeof parsed !== 'object' || !Array.isArray(parsed.spawns)) return { spawns: [] };
57
- return parsed;
58
- } catch (_) {
59
- return { spawns: [] };
60
- }
61
- }
62
-
63
- function _writeIndex(projectDir, idx) {
64
- const p = _indexPath(projectDir);
65
- _ensureDir(path.dirname(p));
66
- const tmp = p + '.tmp';
67
- fs.writeFileSync(tmp, JSON.stringify(idx, null, 2));
68
- fs.renameSync(tmp, p);
69
- }
70
-
71
- /**
72
- * Register a new transcript + create the ndjson file.
73
- *
74
- * @param {object} opts
75
- * @param {string} opts.spawnId
76
- * @param {string} [opts.projectDir='.']
77
- * @param {object} [opts.meta] { parentId?, command?, description?, workerPid?, model? }
78
- * @returns {{spawnId, transcriptPath, startedAt}}
79
- */
80
- function openTranscript(opts) {
81
- if (!opts || !opts.spawnId) throw new Error('openTranscript: spawnId required');
82
- const projectDir = opts.projectDir || '.';
83
- const meta = opts.meta || {};
84
- const dir = _transcriptsDir(projectDir);
85
- _ensureDir(dir);
86
-
87
- const transcriptPath = path.join(dir, `${opts.spawnId}.ndjson`);
88
- if (!fs.existsSync(transcriptPath)) {
89
- fs.writeFileSync(transcriptPath, '');
90
- }
91
-
92
- const startedAt = new Date().toISOString();
93
- const entry = {
94
- spawnId: opts.spawnId,
95
- parentId: meta.parentId || null,
96
- command: meta.command || null,
97
- description: meta.description || null,
98
- model: meta.model || null,
99
- workerPid: meta.workerPid || null,
100
- startedAt,
101
- endedAt: null,
102
- status: 'running',
103
- };
104
-
105
- const idx = _readIndex(projectDir);
106
- const existing = idx.spawns.findIndex((s) => s.spawnId === opts.spawnId);
107
- if (existing >= 0) {
108
- idx.spawns[existing] = { ...idx.spawns[existing], ...entry };
109
- } else {
110
- idx.spawns.push(entry);
111
- }
112
- _writeIndex(projectDir, idx);
113
-
114
- return { spawnId: opts.spawnId, transcriptPath, startedAt };
115
- }
116
-
117
- /**
118
- * Append a single frame (already JSON-serializable) to the transcript.
119
- * `frame` may be a parsed object OR a raw string line — strings are wrapped
120
- * as `{type:"raw",line}` so the ndjson shape stays uniform.
121
- *
122
- * @param {object} opts
123
- * @param {string} opts.spawnId
124
- * @param {string} [opts.projectDir='.']
125
- * @param {object|string} opts.frame
126
- */
127
- function appendFrame(opts) {
128
- if (!opts || !opts.spawnId) throw new Error('appendFrame: spawnId required');
129
- if (opts.frame === undefined || opts.frame === null) return;
130
- const projectDir = opts.projectDir || '.';
131
- const p = path.join(_transcriptsDir(projectDir), `${opts.spawnId}.ndjson`);
132
- _ensureDir(path.dirname(p));
133
-
134
- let line;
135
- if (typeof opts.frame === 'string') {
136
- const trimmed = opts.frame.trim();
137
- if (!trimmed) return;
138
- try {
139
- JSON.parse(trimmed);
140
- line = trimmed;
141
- } catch (_) {
142
- line = JSON.stringify({ type: 'raw', line: opts.frame });
143
- }
144
- } else {
145
- try {
146
- line = JSON.stringify(opts.frame);
147
- } catch (_) {
148
- line = JSON.stringify({ type: 'raw', line: String(opts.frame) });
149
- }
150
- }
151
- fs.appendFileSync(p, line + '\n');
152
- }
153
-
154
- /**
155
- * Mark a transcript as ended. Idempotent — subsequent calls update endedAt.
156
- *
157
- * @param {object} opts
158
- * @param {string} opts.spawnId
159
- * @param {string} [opts.projectDir='.']
160
- * @param {'done'|'failed'|'stopped'|'ended'} [opts.status='ended']
161
- */
162
- function closeTranscript(opts) {
163
- if (!opts || !opts.spawnId) throw new Error('closeTranscript: spawnId required');
164
- const projectDir = opts.projectDir || '.';
165
- const idx = _readIndex(projectDir);
166
- const i = idx.spawns.findIndex((s) => s.spawnId === opts.spawnId);
167
- if (i < 0) return false;
168
- idx.spawns[i].endedAt = new Date().toISOString();
169
- idx.spawns[i].status = opts.status || 'ended';
170
- _writeIndex(projectDir, idx);
171
- return true;
172
- }
173
-
174
- /**
175
- * List registered spawns (most recent first).
176
- *
177
- * @param {string} [projectDir='.']
178
- * @returns {Array<object>}
179
- */
180
- function listTranscripts(projectDir) {
181
- const idx = _readIndex(projectDir || '.');
182
- return idx.spawns.slice().sort((a, b) => {
183
- const ta = Date.parse(a.startedAt) || 0;
184
- const tb = Date.parse(b.startedAt) || 0;
185
- return tb - ta;
186
- });
187
- }
188
-
189
- function readTranscriptMeta(projectDir, spawnId) {
190
- const idx = _readIndex(projectDir || '.');
191
- return idx.spawns.find((s) => s.spawnId === spawnId) || null;
192
- }
193
-
194
- /**
195
- * Tee a stream-json stdout stream. Returns an `onChunk(buffer)` callback that
196
- * you feed chunks to (typed as Buffer or string). Frames are split at `\n`
197
- * and each complete line is written to the transcript ndjson. Incomplete
198
- * tails are buffered until the next chunk.
199
- *
200
- * Returns also a `flush()` to call on child exit — writes any stranded tail
201
- * as a single `{type:"raw"}` line so nothing is dropped.
202
- *
203
- * @param {object} opts
204
- * @param {string} opts.spawnId
205
- * @param {string} [opts.projectDir='.']
206
- * @returns {{onChunk: (chunk) => void, flush: () => void}}
207
- */
208
- function makeStreamTee(opts) {
209
- if (!opts || !opts.spawnId) throw new Error('makeStreamTee: spawnId required');
210
- const projectDir = opts.projectDir || '.';
211
- const spawnId = opts.spawnId;
212
- let buf = '';
213
-
214
- return {
215
- onChunk(chunk) {
216
- if (chunk == null) return;
217
- buf += Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk);
218
- let nl;
219
- while ((nl = buf.indexOf('\n')) >= 0) {
220
- const line = buf.slice(0, nl);
221
- buf = buf.slice(nl + 1);
222
- if (line.length > 0) appendFrame({ spawnId, projectDir, frame: line });
223
- }
224
- },
225
- flush() {
226
- if (buf.length > 0) {
227
- appendFrame({ spawnId, projectDir, frame: buf });
228
- buf = '';
229
- }
230
- },
231
- };
232
- }
233
-
234
- module.exports = {
235
- allocateSpawnId,
236
- openTranscript,
237
- appendFrame,
238
- closeTranscript,
239
- listTranscripts,
240
- readTranscriptMeta,
241
- makeStreamTee,
242
- _readIndex,
243
- _writeIndex,
244
- TRANSCRIPTS_DIRNAME,
245
- INDEX_FILENAME,
246
- };
@@ -1,188 +0,0 @@
1
- /**
2
- * gsd-t-unattended-heartbeat.cjs
3
- *
4
- * Liveness heartbeat watchdog for the unattended supervisor.
5
- *
6
- * Supersedes the pre-M43 `workerTimeoutMs` wall-clock guillotine as the
7
- * PRIMARY stuck-worker detector. The guillotine remains as an absolute
8
- * backstop (raised to 1 hour by default) for pathological cases where a
9
- * child never writes a single event.
10
- *
11
- * How it works
12
- * ────────────
13
- * The supervisor polls `.gsd-t/events/YYYY-MM-DD.jsonl` mtime every 60 s
14
- * during a worker iteration. If the mtime has not advanced for at least
15
- * `staleHeartbeatMs` (default 300_000 = 5 min), the worker is considered
16
- * stuck and SIGTERM'd. Healthy workers producing events run indefinitely
17
- * under the 1-hour absolute cap.
18
- *
19
- * This module is pure and side-effect-free by default. `checkHeartbeat()`
20
- * accepts injected `now` and `fsShim` so the entire watchdog can be
21
- * unit-tested with a fake clock and fake filesystem.
22
- *
23
- * Zero external dependencies — Node built-ins only.
24
- *
25
- * Contract: .gsd-t/contracts/unattended-supervisor-contract.md v1.1.0
26
- * §"Heartbeat Watchdog"
27
- */
28
-
29
- "use strict";
30
-
31
- const fs = require("node:fs");
32
- const path = require("node:path");
33
-
34
- /**
35
- * Build the events JSONL path for a given date.
36
- *
37
- * @param {string} projectDir
38
- * @param {Date|number} when Date, or ms since epoch. Defaults to now when
39
- * omitted at the call site.
40
- * @returns {string}
41
- */
42
- function eventsPathFor(projectDir, when) {
43
- const d = when instanceof Date ? when : new Date(when || Date.now());
44
- const y = d.getUTCFullYear();
45
- const m = String(d.getUTCMonth() + 1).padStart(2, "0");
46
- const day = String(d.getUTCDate()).padStart(2, "0");
47
- return path.join(projectDir, ".gsd-t", "events", `${y}-${m}-${day}.jsonl`);
48
- }
49
-
50
- /**
51
- * Check whether the worker's event stream is stale.
52
- *
53
- * A worker is "stale" when the relevant events JSONL file's mtime has not
54
- * advanced within `staleHeartbeatMs` of the given `now`. The relevant file
55
- * is the one matching the date of `now` — if the loop crosses a UTC day
56
- * boundary mid-iteration, the new day's file is checked.
57
- *
58
- * Fresh worker grace: if the events file does not exist yet AND
59
- * `(now - workerStartedAt) < staleHeartbeatMs`, the worker is considered
60
- * healthy (still booting). After the grace window with no file, the worker
61
- * is stale.
62
- *
63
- * @param {object} params
64
- * @param {string} params.projectDir
65
- * @param {number} params.workerStartedAt ms since epoch
66
- * @param {number} params.staleHeartbeatMs
67
- * @param {number} [params.now] ms since epoch (defaults to Date.now())
68
- * @param {object} [params.fsShim] { existsSync, statSync } — test hook
69
- * @returns {{stale: boolean, reason: string, lastEventMs: (number|null), ageMs: (number|null), eventsPath: string}}
70
- */
71
- function checkHeartbeat({
72
- projectDir,
73
- workerStartedAt,
74
- staleHeartbeatMs,
75
- now,
76
- fsShim,
77
- }) {
78
- if (typeof projectDir !== "string" || projectDir.length === 0) {
79
- throw new Error("checkHeartbeat: projectDir is required");
80
- }
81
- if (typeof workerStartedAt !== "number" || !Number.isFinite(workerStartedAt)) {
82
- throw new Error("checkHeartbeat: workerStartedAt must be a finite number");
83
- }
84
- if (
85
- typeof staleHeartbeatMs !== "number" ||
86
- !Number.isFinite(staleHeartbeatMs) ||
87
- staleHeartbeatMs <= 0
88
- ) {
89
- throw new Error("checkHeartbeat: staleHeartbeatMs must be a positive number");
90
- }
91
- const nowMs = typeof now === "number" ? now : Date.now();
92
- const shim = fsShim || fs;
93
-
94
- const eventsPath = eventsPathFor(projectDir, nowMs);
95
-
96
- let exists = false;
97
- try {
98
- exists = !!shim.existsSync(eventsPath);
99
- } catch (_) {
100
- exists = false;
101
- }
102
-
103
- if (!exists) {
104
- const sinceStart = nowMs - workerStartedAt;
105
- if (sinceStart < staleHeartbeatMs) {
106
- return {
107
- stale: false,
108
- reason: `events file not yet created (grace: ${sinceStart}ms < ${staleHeartbeatMs}ms)`,
109
- lastEventMs: null,
110
- ageMs: null,
111
- eventsPath,
112
- };
113
- }
114
- return {
115
- stale: true,
116
- reason: `events file ${eventsPath} absent for ${sinceStart}ms since worker start (threshold ${staleHeartbeatMs}ms)`,
117
- lastEventMs: null,
118
- ageMs: sinceStart,
119
- eventsPath,
120
- };
121
- }
122
-
123
- let stat;
124
- try {
125
- stat = shim.statSync(eventsPath);
126
- } catch (err) {
127
- // File existed at existsSync but stat failed — treat as stale only if
128
- // we are past the grace window. Under the grace window, assume transient.
129
- const sinceStart = nowMs - workerStartedAt;
130
- if (sinceStart < staleHeartbeatMs) {
131
- return {
132
- stale: false,
133
- reason: `events stat transient failure (grace): ${err.message}`,
134
- lastEventMs: null,
135
- ageMs: null,
136
- eventsPath,
137
- };
138
- }
139
- return {
140
- stale: true,
141
- reason: `events stat failed past grace: ${err.message}`,
142
- lastEventMs: null,
143
- ageMs: sinceStart,
144
- eventsPath,
145
- };
146
- }
147
-
148
- const mtimeMs =
149
- typeof stat.mtimeMs === "number"
150
- ? stat.mtimeMs
151
- : stat.mtime instanceof Date
152
- ? stat.mtime.getTime()
153
- : 0;
154
-
155
- // Reference point for staleness: max(mtime, workerStartedAt). This handles
156
- // the bootstrap case where the events file already existed from a prior
157
- // iteration — we don't want to kill the worker on its first 60s poll just
158
- // because it hasn't emitted yet. The worker gets at least staleHeartbeatMs
159
- // from its own start to produce the first event.
160
- const ref = Math.max(mtimeMs, workerStartedAt);
161
- const ageMs = nowMs - ref;
162
-
163
- if (ageMs >= staleHeartbeatMs) {
164
- return {
165
- stale: true,
166
- reason: `last event ${ageMs}ms ago (threshold ${staleHeartbeatMs}ms)`,
167
- lastEventMs: mtimeMs,
168
- ageMs,
169
- eventsPath,
170
- };
171
- }
172
- return {
173
- stale: false,
174
- reason: `fresh — last event ${ageMs}ms ago`,
175
- lastEventMs: mtimeMs,
176
- ageMs,
177
- eventsPath,
178
- };
179
- }
180
-
181
- module.exports = {
182
- checkHeartbeat,
183
- eventsPathFor,
184
- // Default heartbeat poll cadence — exported so tests and the supervisor
185
- // can reference a single source of truth.
186
- DEFAULT_HEARTBEAT_POLL_MS: 60 * 1000,
187
- DEFAULT_STALE_HEARTBEAT_MS: 5 * 60 * 1000,
188
- };