@tekyzinc/gsd-t 3.29.10 → 4.0.12

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 (112) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/bin/gsd-t-parallel.cjs +64 -13
  3. package/bin/gsd-t-test-data-adapters/file-json-array.cjs +27 -3
  4. package/bin/gsd-t-test-data-adapters/localstorage-key-prefix.cjs +6 -1
  5. package/bin/gsd-t-test-data-adapters/sqlite-table-where.cjs +16 -1
  6. package/bin/gsd-t-test-data-ledger.cjs +1 -0
  7. package/bin/gsd-t.js +48 -376
  8. package/bin/journey-coverage.cjs +6 -3
  9. package/bin/parallel-cli.cjs +13 -1
  10. package/commands/gsd-t-debug.md +47 -533
  11. package/commands/gsd-t-design-decompose.md +24 -497
  12. package/commands/gsd-t-doc-ripple.md +23 -139
  13. package/commands/gsd-t-execute.md +41 -958
  14. package/commands/gsd-t-help.md +0 -2
  15. package/commands/gsd-t-impact.md +26 -295
  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-verify.md +52 -569
  24. package/commands/gsd-t-wave.md +41 -430
  25. package/package.json +1 -1
  26. package/scripts/gsd-t-calibration-hook.js +3 -1
  27. package/scripts/hooks/pre-commit-journey-coverage +0 -2
  28. package/scripts/hooks/pre-commit-playwright-gate +0 -2
  29. package/templates/CLAUDE-global.md +43 -173
  30. package/templates/CLAUDE-project.md +118 -104
  31. package/templates/prompts/design-verify-subagent.md +3 -0
  32. package/templates/prompts/qa-subagent.md +3 -0
  33. package/templates/prompts/red-team-subagent.md +5 -2
  34. package/templates/workflows/_lib.js +176 -0
  35. package/templates/workflows/gsd-t-debug.workflow.js +86 -0
  36. package/templates/workflows/gsd-t-execute.workflow.js +206 -0
  37. package/templates/workflows/gsd-t-integrate.workflow.js +71 -0
  38. package/templates/workflows/gsd-t-phase.workflow.js +94 -0
  39. package/templates/workflows/gsd-t-quick.workflow.js +72 -0
  40. package/templates/workflows/gsd-t-verify.workflow.js +348 -0
  41. package/templates/workflows/gsd-t-wave.workflow.js +43 -0
  42. package/bin/check-headless-sessions.js +0 -140
  43. package/bin/context-budget-audit.cjs +0 -447
  44. package/bin/context-meter-config.cjs +0 -101
  45. package/bin/context-meter-config.test.cjs +0 -101
  46. package/bin/event-stream.cjs +0 -205
  47. package/bin/gsd-t-benchmark-orchestrator.js +0 -437
  48. package/bin/gsd-t-capture-lint.cjs +0 -440
  49. package/bin/gsd-t-economics.cjs +0 -315
  50. package/bin/gsd-t-in-session-usage.cjs +0 -213
  51. package/bin/gsd-t-orchestrator-config.cjs +0 -161
  52. package/bin/gsd-t-orchestrator-queue.cjs +0 -180
  53. package/bin/gsd-t-orchestrator-recover.cjs +0 -231
  54. package/bin/gsd-t-orchestrator-worker.cjs +0 -219
  55. package/bin/gsd-t-orchestrator.js +0 -535
  56. package/bin/gsd-t-parallel-probe.cjs +0 -132
  57. package/bin/gsd-t-ratelimit-probe-worker.cjs +0 -237
  58. package/bin/gsd-t-ratelimit-probe.cjs +0 -648
  59. package/bin/gsd-t-report-tokens.cjs +0 -549
  60. package/bin/gsd-t-stream-feed-client.cjs +0 -151
  61. package/bin/gsd-t-token-backfill.cjs +0 -366
  62. package/bin/gsd-t-token-capture.cjs +0 -321
  63. package/bin/gsd-t-token-dashboard.cjs +0 -353
  64. package/bin/gsd-t-token-regenerate-log.cjs +0 -129
  65. package/bin/gsd-t-tool-attribution.cjs +0 -377
  66. package/bin/gsd-t-tool-cost.cjs +0 -195
  67. package/bin/gsd-t-transcript-tee.cjs +0 -246
  68. package/bin/gsd-t-unattended-heartbeat.cjs +0 -188
  69. package/bin/gsd-t-unattended-platform.cjs +0 -551
  70. package/bin/gsd-t-unattended-platform.js +0 -381
  71. package/bin/gsd-t-unattended-safety.cjs +0 -773
  72. package/bin/gsd-t-unattended-safety.js +0 -788
  73. package/bin/gsd-t-unattended.cjs +0 -2109
  74. package/bin/gsd-t-unattended.js +0 -1367
  75. package/bin/gsd-t-worker-dispatch.cjs +0 -211
  76. package/bin/handoff-lock.cjs +0 -249
  77. package/bin/handoff-lock.js +0 -249
  78. package/bin/headless-auto-spawn.cjs +0 -711
  79. package/bin/headless-auto-spawn.js +0 -373
  80. package/bin/headless-exit-codes.cjs +0 -67
  81. package/bin/live-activity-report.cjs +0 -615
  82. package/bin/log-tail.cjs +0 -81
  83. package/bin/m44-proof-measure.cjs +0 -285
  84. package/bin/m46-iter-proof.cjs +0 -149
  85. package/bin/m46-worker-proof.cjs +0 -201
  86. package/bin/m55-substrate-proof.cjs +0 -134
  87. package/bin/metrics-rollup.js +0 -200
  88. package/bin/model-windows.cjs +0 -99
  89. package/bin/model-windows.test.cjs +0 -75
  90. package/bin/parallelism-report.cjs +0 -535
  91. package/bin/runway-estimator.cjs +0 -242
  92. package/bin/spawn-plan-derive.cjs +0 -163
  93. package/bin/spawn-plan-status-updater.cjs +0 -292
  94. package/bin/spawn-plan-writer.cjs +0 -204
  95. package/bin/supervisor-pid-fingerprint.cjs +0 -126
  96. package/bin/token-budget.cjs +0 -265
  97. package/bin/unattended-watch-format.cjs +0 -178
  98. package/bin/watch-progress.js +0 -155
  99. package/commands/gsd-t-unattended-stop.md +0 -85
  100. package/commands/gsd-t-unattended-watch.md +0 -465
  101. package/commands/gsd-t-unattended.md +0 -476
  102. package/commands/gsd-t-visualize.md +0 -116
  103. package/scripts/gsd-t-context-meter.e2e.test.js +0 -364
  104. package/scripts/gsd-t-context-meter.js +0 -341
  105. package/scripts/gsd-t-context-meter.test.js +0 -471
  106. package/scripts/gsd-t-dashboard-server.js +0 -1203
  107. package/scripts/gsd-t-post-commit-spawn-plan.sh +0 -86
  108. package/scripts/gsd-t-transcript.html +0 -1821
  109. package/scripts/hooks/gsd-t-conversation-capture.js +0 -439
  110. package/scripts/hooks/gsd-t-in-session-usage-hook.js +0 -84
  111. package/scripts/spawn-plan-fmt-tokens.cjs +0 -80
  112. 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
- };