@sentropic/h2a-runtime 0.98.6 → 0.98.7-rc.1

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 (58) hide show
  1. package/dist/attach.d.ts +2 -0
  2. package/dist/attach.d.ts.map +1 -1
  3. package/dist/attach.js +73 -6
  4. package/dist/attach.js.map +1 -1
  5. package/dist/auth-login.d.ts +24 -1
  6. package/dist/auth-login.d.ts.map +1 -1
  7. package/dist/auth-login.js +132 -4
  8. package/dist/auth-login.js.map +1 -1
  9. package/dist/central-mcp.d.ts +2 -0
  10. package/dist/central-mcp.d.ts.map +1 -1
  11. package/dist/central-mcp.js +90 -3
  12. package/dist/central-mcp.js.map +1 -1
  13. package/dist/cli-help-groups.js +1 -1
  14. package/dist/cli-help-groups.js.map +1 -1
  15. package/dist/crash-log.d.ts +112 -0
  16. package/dist/crash-log.d.ts.map +1 -0
  17. package/dist/crash-log.js +560 -0
  18. package/dist/crash-log.js.map +1 -0
  19. package/dist/gateway-host/live-declarations.d.ts +58 -0
  20. package/dist/gateway-host/live-declarations.d.ts.map +1 -0
  21. package/dist/gateway-host/live-declarations.js +423 -0
  22. package/dist/gateway-host/live-declarations.js.map +1 -0
  23. package/dist/gateway-host/live-registration.d.ts +162 -0
  24. package/dist/gateway-host/live-registration.d.ts.map +1 -0
  25. package/dist/gateway-host/live-registration.js +455 -0
  26. package/dist/gateway-host/live-registration.js.map +1 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +79 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/native-host.d.ts.map +1 -1
  31. package/dist/native-host.js +27 -5
  32. package/dist/native-host.js.map +1 -1
  33. package/dist/native-terminal/journal.d.ts +5 -0
  34. package/dist/native-terminal/journal.d.ts.map +1 -1
  35. package/dist/native-terminal/journal.js +28 -16
  36. package/dist/native-terminal/journal.js.map +1 -1
  37. package/dist/native-terminal/op.d.ts +13 -0
  38. package/dist/native-terminal/op.d.ts.map +1 -1
  39. package/dist/native-terminal/op.js +64 -5
  40. package/dist/native-terminal/op.js.map +1 -1
  41. package/dist/run.d.ts.map +1 -1
  42. package/dist/run.js +79 -16
  43. package/dist/run.js.map +1 -1
  44. package/dist/terminal-reset.d.ts +104 -0
  45. package/dist/terminal-reset.d.ts.map +1 -0
  46. package/dist/terminal-reset.js +229 -0
  47. package/dist/terminal-reset.js.map +1 -0
  48. package/dist/tmux.d.ts +23 -3
  49. package/dist/tmux.d.ts.map +1 -1
  50. package/dist/tmux.js +47 -16
  51. package/dist/tmux.js.map +1 -1
  52. package/dist/vendor/engram-live/contracts.d.ts +208 -0
  53. package/dist/vendor/engram-live/contracts.js +558 -0
  54. package/dist/vendor/engram-live/integration.d.ts +73 -0
  55. package/dist/vendor/engram-live/integration.js +194 -0
  56. package/dist/vendor/engram-live/registration.d.ts +138 -0
  57. package/dist/vendor/engram-live/registration.js +360 -0
  58. package/package.json +2 -2
@@ -0,0 +1,560 @@
1
+ /**
2
+ * Crash logs: one documented, rotated, bounded JSONL log per component.
3
+ *
4
+ * Components:
5
+ * - `native-host` → the existing life journal
6
+ * (`native-terminal/journal.ts`, `native-host.log`) — read-only here,
7
+ * owned by the native host process. Documented, not duplicated.
8
+ * - `cli` → launcher/op failures (`native-host.ts` runOp/admission refusals).
9
+ * - `attach` → attach-client detach/give-up reasons (remote `attach.ts` and
10
+ * the native `op.ts attach` bridge).
11
+ * - `mcp-server` → central MCP spawn/readiness failures (`central-mcp.ts`).
12
+ *
13
+ * Every row carries timestamp, component, version, pid, session/instance id
14
+ * when known, and a structured fatal record (uncaught exception, refusal with
15
+ * reason, child exit with code/signal). Files live under
16
+ * `${XDG_STATE_HOME:-$HOME/.local/state}/h2a/`, mode 0600, dir 0700, rotated
17
+ * at MAX_CRASH_LOG_BYTES (current + one `.1` generation, both read by
18
+ * `readRecentCrashLogs`). Structured rows never carry secrets in the clear:
19
+ * values are redacted before serialization (see `redactCrashText`, which
20
+ * stands on its own even when the secret is absent from the writer's
21
+ * environment). (The raw `mcp-central.log` server dump is verbatim child
22
+ * output and stays unredacted at rest; `h2a logs` redacts it on display.)
23
+ * Exit codes and signals are only ever observed values: either field is
24
+ * omitted when unknown, never defaulted. Appends take one lock attempt plus
25
+ * one provably-dead orphan reclaim (stale age AND dead owner PID); contention
26
+ * drops the row (counted via `getCrashLogDrops` and surfaced as a `dropped`
27
+ * row on the next successful append in the same process).
28
+ */
29
+ import { randomUUID } from "node:crypto";
30
+ import { chmodSync, closeSync, constants, fchmodSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, renameSync, statSync, unlinkSync, writeSync, } from "node:fs";
31
+ import { homedir } from "node:os";
32
+ import { dirname, isAbsolute, join } from "node:path";
33
+ export const CRASH_LOG_COMPONENTS = ["cli", "attach", "mcp-server"];
34
+ export const NATIVE_HOST_LOG_COMPONENT = "native-host";
35
+ export const MAX_CRASH_LOG_BYTES = 512 * 1024;
36
+ const CRASH_LOG_FILES = {
37
+ cli: "cli.log",
38
+ attach: "attach.log",
39
+ "mcp-server": "mcp-server.log",
40
+ };
41
+ export function resolveCrashLogPath(component, env = process.env) {
42
+ const state = env["XDG_STATE_HOME"];
43
+ const base = state && isAbsolute(state)
44
+ ? join(state, "h2a")
45
+ : join(env["HOME"] || homedir(), ".local", "state", "h2a");
46
+ return join(base, CRASH_LOG_FILES[component]);
47
+ }
48
+ /** State dir shared by all crash logs (and the native host journal). */
49
+ export function resolveCrashLogDir(env = process.env) {
50
+ const state = env["XDG_STATE_HOME"];
51
+ if (state && isAbsolute(state))
52
+ return join(state, "h2a");
53
+ return join(env["HOME"] || homedir(), ".local", "state", "h2a");
54
+ }
55
+ let cachedVersion;
56
+ export function getCrashLogVersion() {
57
+ if (cachedVersion !== undefined)
58
+ return cachedVersion;
59
+ try {
60
+ const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
61
+ cachedVersion = typeof pkg.version === "string" ? pkg.version : "unknown";
62
+ }
63
+ catch {
64
+ cachedVersion = "unknown";
65
+ }
66
+ return cachedVersion;
67
+ }
68
+ /** Test-only: reset the cached version. */
69
+ export function resetCrashLogVersionForTests() {
70
+ cachedVersion = undefined;
71
+ }
72
+ const PATH_ENV_KEYS = new Set([
73
+ "HOME",
74
+ "PATH",
75
+ "PWD",
76
+ "OLDPWD",
77
+ "TMPDIR",
78
+ "NODE_PATH",
79
+ "TERM",
80
+ "LANG",
81
+ "XDG_RUNTIME_DIR",
82
+ "XDG_STATE_HOME",
83
+ "XDG_CONFIG_HOME",
84
+ ]);
85
+ /**
86
+ * Redact secret values and credential patterns; never throws. Pattern
87
+ * redaction stands on its own: it must hold even when the secret value is
88
+ * absent from the writer's environment (tokens in child stderr, config JSON,
89
+ * CLI flags). Fail closed — an unrecognized `name=value` shape that names a
90
+ * credential is redacted, never passed through.
91
+ */
92
+ export function redactCrashText(value) {
93
+ let result = value.slice(0, 4096);
94
+ try {
95
+ for (const [key, secret] of Object.entries(process.env)) {
96
+ if (!PATH_ENV_KEYS.has(key) && secret && secret.length >= 4) {
97
+ result = result.split(secret).join("[REDACTED]");
98
+ }
99
+ }
100
+ }
101
+ catch {
102
+ /* redaction best-effort */
103
+ }
104
+ // Fail closed over shapes, not an enumeration of names: dash/underscore
105
+ // cross in every motif, header names match quoted/JSON/`=` forms, values
106
+ // keep commas (passwords) but stop at `&`/`;`/whitespace (query chains).
107
+ return result
108
+ .replace(/-----BEGIN [^-]*PRIVATE KEY-----[\s\S]*?-----END [^-]*PRIVATE KEY-----/g, "[REDACTED]")
109
+ .replace(/\b(?:bearer|basic)\s+\S+/gi, "[REDACTED]")
110
+ .replace(/["']?(?:authorization|cookie|set-cookie)["']?\s*[:=]\s*("[^"\r\n]*"|'[^'\r\n]*'|[^\s;&"']+)/gi, "[REDACTED]")
111
+ .replace(/["']?[\w.-]*?(?:access[_-]?token|refresh[_-]?token|client[_-]?secret|id[_-]?token|auth[_-]?token|private[_-]?key|api[_-]?key|token|secret|passwd|passphrase|password|credential|pass|pwd|auth|session|key)["']?\s*[:=]\s*("[^"\r\n]*"|'[^'\r\n]*'|[^\s;&"']+)/gi, "[REDACTED]")
112
+ .replace(/(--?(?:access[_-]?token|refresh[_-]?token|client[_-]?secret|id[_-]?token|auth[_-]?token|private[_-]?key|api[_-]?key|token|secret|password|passwd|passphrase|pass|pwd|auth|session|credential|key))\b\s+("[^"\r\n]*"|'[^'\r\n]*'|[^\s"']+)/gi, "$1 [REDACTED]")
113
+ .replace(/:\/\/[^/\s]*@/g, "://[REDACTED]@");
114
+ }
115
+ const CRASH_SIGNAL_NUMBERS = {
116
+ 1: "SIGHUP",
117
+ 2: "SIGINT",
118
+ 3: "SIGQUIT",
119
+ 4: "SIGILL",
120
+ 5: "SIGTRAP",
121
+ 6: "SIGABRT",
122
+ 7: "SIGBUS",
123
+ 8: "SIGFPE",
124
+ 9: "SIGKILL",
125
+ 10: "SIGUSR1",
126
+ 11: "SIGSEGV",
127
+ 12: "SIGUSR2",
128
+ 13: "SIGPIPE",
129
+ 14: "SIGALRM",
130
+ 15: "SIGTERM",
131
+ 16: "SIGSTKFLT",
132
+ 17: "SIGCHLD",
133
+ 18: "SIGCONT",
134
+ 19: "SIGSTOP",
135
+ 20: "SIGTSTP",
136
+ 21: "SIGTTIN",
137
+ 22: "SIGTTOU",
138
+ 23: "SIGURG",
139
+ 24: "SIGXCPU",
140
+ 25: "SIGXFSZ",
141
+ 26: "SIGVTALRM",
142
+ 27: "SIGPROF",
143
+ 28: "SIGWINCH",
144
+ 29: "SIGIO",
145
+ 30: "SIGPWR",
146
+ 31: "SIGSYS",
147
+ };
148
+ /**
149
+ * Normalize a signal (name, signo, or numeric string) to a log-safe name.
150
+ * Unknown names become `"unknown"`; unknown numbers become `"SIG<n>"` so the
151
+ * signo survives. `undefined` stays `undefined` — callers omit the field
152
+ * instead of inventing a signal.
153
+ */
154
+ export function crashSignalName(value) {
155
+ if (value === undefined)
156
+ return undefined;
157
+ const text = typeof value === "number" ? String(value) : value.trim();
158
+ if (/^\d+$/.test(text)) {
159
+ const signo = Number.parseInt(text, 10);
160
+ if (Number.isSafeInteger(signo))
161
+ return CRASH_SIGNAL_NUMBERS[signo] ?? `SIG${signo}`;
162
+ }
163
+ if (typeof value === "string" && /^[A-Z][A-Z0-9_]{1,15}$/.test(value))
164
+ return value;
165
+ return "unknown";
166
+ }
167
+ function sanitizeField(value) {
168
+ if (value === undefined)
169
+ return undefined;
170
+ const clean = redactCrashText(value).slice(0, 1024);
171
+ return clean.length > 0 ? clean : undefined;
172
+ }
173
+ function sanitizeEvent(event) {
174
+ const known = [
175
+ "start",
176
+ "uncaughtException",
177
+ "unhandledRejection",
178
+ "startupError",
179
+ "refusal",
180
+ "childExit",
181
+ "sessionExit",
182
+ "signal",
183
+ "stop",
184
+ "exit",
185
+ "dropped",
186
+ ];
187
+ return known.includes(event) ? event : "exit";
188
+ }
189
+ function sanitizeSignal(signal) {
190
+ return crashSignalName(signal);
191
+ }
192
+ export function toCrashLogRow(component, entry) {
193
+ const row = {
194
+ timestamp: new Date().toISOString(),
195
+ component,
196
+ version: getCrashLogVersion(),
197
+ pid: process.pid,
198
+ event: sanitizeEvent(entry.event),
199
+ };
200
+ const sessionId = sanitizeField(entry.sessionId);
201
+ const instanceId = sanitizeField(entry.instanceId);
202
+ const reason = sanitizeField(entry.reason);
203
+ const detail = sanitizeField(entry.detail);
204
+ const signal = sanitizeSignal(entry.signal);
205
+ return {
206
+ ...row,
207
+ ...(sessionId ? { sessionId } : {}),
208
+ ...(instanceId ? { instanceId } : {}),
209
+ ...(reason ? { reason } : {}),
210
+ ...(detail ? { detail } : {}),
211
+ ...(Number.isSafeInteger(entry.exitCode) ? { exitCode: entry.exitCode } : {}),
212
+ ...(signal ? { signal } : {}),
213
+ };
214
+ }
215
+ function privateFile(fd) {
216
+ const info = fstatSync(fd);
217
+ if (!info.isFile() ||
218
+ info.nlink !== 1 ||
219
+ (typeof process.getuid === "function" && info.uid !== process.getuid())) {
220
+ throw new Error("unsafe crash log file");
221
+ }
222
+ fchmodSync(fd, 0o600);
223
+ }
224
+ function writeAll(fd, text) {
225
+ const bytes = Buffer.from(text);
226
+ for (let offset = 0; offset < bytes.length;) {
227
+ const written = writeSync(fd, bytes, offset, bytes.length - offset);
228
+ if (written <= 0)
229
+ throw new Error("crash log write made no progress");
230
+ offset += written;
231
+ }
232
+ }
233
+ /**
234
+ * A lock older than this was left by a dead writer: its owner can never come
235
+ * back to release it, so the next writer reclaims it instead of letting the
236
+ * component's log go silent forever. A live lock still drops (returns false).
237
+ */
238
+ export const CRASH_LOG_LOCK_STALE_MS = 10_000;
239
+ let droppedCrashLogs = 0;
240
+ const pendingCrashLogDrops = new Map();
241
+ function dropCrashLog(logPath, count = 1) {
242
+ droppedCrashLogs += count;
243
+ pendingCrashLogDrops.set(logPath, (pendingCrashLogDrops.get(logPath) ?? 0) + count);
244
+ }
245
+ /** Process-lifetime count of crash-log rows dropped instead of appended. */
246
+ export function getCrashLogDrops() {
247
+ return droppedCrashLogs;
248
+ }
249
+ function acquireCrashLogLock(lockPath, token) {
250
+ try {
251
+ const fd = openSync(lockPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 0o600);
252
+ writeAll(fd, token);
253
+ return fd;
254
+ }
255
+ catch (error) {
256
+ if (error.code !== "EEXIST")
257
+ throw error;
258
+ }
259
+ // Contended. Reclaim only a provably-dead orphan: age alone never proves
260
+ // death (a live writer blocked in the filesystem never refreshes its
261
+ // mtime), so the owner PID in the lock token must be dead too. A live lock,
262
+ // an unreadable token, or a lock that changed under us drops the row
263
+ // instead of blocking the fatal path.
264
+ try {
265
+ const ageMs = Date.now() - statSync(lockPath).mtimeMs;
266
+ if (!Number.isFinite(ageMs) || ageMs < CRASH_LOG_LOCK_STALE_MS)
267
+ return undefined;
268
+ let owner = NaN;
269
+ try {
270
+ owner = Number.parseInt(String(readFileSync(lockPath, "utf8")).split(":")[0] ?? "", 10);
271
+ }
272
+ catch {
273
+ return undefined;
274
+ }
275
+ if (!Number.isSafeInteger(owner) || owner <= 0)
276
+ return undefined;
277
+ try {
278
+ process.kill(owner, 0);
279
+ return undefined;
280
+ }
281
+ catch (error) {
282
+ // ESRCH = no such process (reclaimable); anything else (EPERM = alive
283
+ // but unowned, or an exotic failure) keeps the lock.
284
+ if (error.code !== "ESRCH")
285
+ return undefined;
286
+ }
287
+ // Re-verify after the liveness probe: a fresh lock that appeared under us
288
+ // (or a token swap) aborts the reclaim instead of unlinking live state.
289
+ try {
290
+ const freshAgeMs = Date.now() - statSync(lockPath).mtimeMs;
291
+ if (!Number.isFinite(freshAgeMs) || freshAgeMs < CRASH_LOG_LOCK_STALE_MS)
292
+ return undefined;
293
+ if (String(readFileSync(lockPath, "utf8")).split(":")[0] !== String(owner))
294
+ return undefined;
295
+ }
296
+ catch {
297
+ return undefined;
298
+ }
299
+ unlinkSync(lockPath);
300
+ const fd = openSync(lockPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 0o600);
301
+ writeAll(fd, token);
302
+ return fd;
303
+ }
304
+ catch {
305
+ return undefined;
306
+ }
307
+ }
308
+ function ensurePrivateCrashLogDir(dir) {
309
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
310
+ let directory = lstatSync(dir);
311
+ // Self-heal a pre-existing group/other-readable state dir we own (tighter
312
+ // is strictly safer); anything else stays a counted drop, never a repair
313
+ // of somebody else's directory.
314
+ if (directory.isDirectory() &&
315
+ (typeof process.getuid !== "function" || directory.uid === process.getuid()) &&
316
+ (directory.mode & 0o077) !== 0) {
317
+ try {
318
+ chmodSync(dir, 0o700);
319
+ }
320
+ catch {
321
+ /* fall through to the safety check below */
322
+ }
323
+ directory = lstatSync(dir);
324
+ }
325
+ if (!directory.isDirectory() ||
326
+ (typeof process.getuid === "function" &&
327
+ directory.uid !== process.getuid()) ||
328
+ (directory.mode & 0o077) !== 0) {
329
+ throw new Error("unsafe crash log directory");
330
+ }
331
+ }
332
+ /**
333
+ * Best-effort bounded append. One lock attempt plus one stale-orphan reclaim,
334
+ * no wait: contention drops the row (returns false, counted and surfaced as a
335
+ * `dropped` row on the next successful append) instead of blocking the fatal
336
+ * path it documents. Never throws.
337
+ */
338
+ export function appendCrashLog(component, entry, logPath = resolveCrashLogPath(component)) {
339
+ let lockFd;
340
+ const lockPath = `${logPath}.lock`;
341
+ const token = `${process.pid}:${randomUUID()}`;
342
+ try {
343
+ const text = `${JSON.stringify(toCrashLogRow(component, entry))}\n`;
344
+ ensurePrivateCrashLogDir(dirname(logPath));
345
+ lockFd = acquireCrashLogLock(lockPath, token);
346
+ if (lockFd === undefined)
347
+ throw new Error("crash log lock contended");
348
+ try {
349
+ const fd = openSync(logPath, constants.O_WRONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
350
+ try {
351
+ privateFile(fd);
352
+ if (fstatSync(fd).size >= MAX_CRASH_LOG_BYTES) {
353
+ try {
354
+ unlinkSync(`${logPath}.1`);
355
+ }
356
+ catch (error) {
357
+ if (error.code !== "ENOENT")
358
+ throw error;
359
+ }
360
+ renameSync(logPath, `${logPath}.1`);
361
+ }
362
+ }
363
+ finally {
364
+ closeSync(fd);
365
+ }
366
+ }
367
+ catch (error) {
368
+ if (error.code !== "ENOENT")
369
+ throw error;
370
+ }
371
+ const fd = openSync(logPath, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW | constants.O_NONBLOCK, 0o600);
372
+ try {
373
+ privateFile(fd);
374
+ // One write for receipt + row, receipt cleared only after it lands: a
375
+ // failed replay keeps the earlier drops instead of losing them.
376
+ const missed = pendingCrashLogDrops.get(logPath) ?? 0;
377
+ const receipt = missed > 0
378
+ ? `${JSON.stringify(toCrashLogRow(component, { event: "dropped", detail: `${missed} crash-log rows dropped (lock contention or unsafe state)` }))}\n`
379
+ : "";
380
+ writeAll(fd, `${receipt}${text}`);
381
+ if (missed > 0)
382
+ pendingCrashLogDrops.delete(logPath);
383
+ }
384
+ finally {
385
+ closeSync(fd);
386
+ }
387
+ return true;
388
+ }
389
+ catch {
390
+ dropCrashLog(logPath);
391
+ return false;
392
+ }
393
+ finally {
394
+ if (lockFd !== undefined) {
395
+ try {
396
+ const owned = fstatSync(lockFd);
397
+ const current = lstatSync(lockPath);
398
+ if (owned.dev === current.dev &&
399
+ owned.ino === current.ino &&
400
+ readFileSync(lockPath, "utf8") === token) {
401
+ unlinkSync(lockPath);
402
+ }
403
+ }
404
+ catch {
405
+ /* Never remove an unproven lock incarnation. */
406
+ }
407
+ try {
408
+ closeSync(lockFd);
409
+ }
410
+ catch {
411
+ /* Crash-log failures never escape. */
412
+ }
413
+ }
414
+ }
415
+ }
416
+ /** Read and parse one crash log; corrupt lines are skipped, never thrown. */
417
+ export function readCrashLog(component, logPath = resolveCrashLogPath(component)) {
418
+ try {
419
+ if (!lstatSync(logPath).isFile())
420
+ return [];
421
+ return readFileSync(logPath, "utf8")
422
+ .split("\n")
423
+ .filter(Boolean)
424
+ .flatMap((line) => {
425
+ try {
426
+ const row = JSON.parse(line);
427
+ if (typeof row !== "object" || row === null)
428
+ return [];
429
+ return [row];
430
+ }
431
+ catch {
432
+ return [];
433
+ }
434
+ });
435
+ }
436
+ catch {
437
+ return [];
438
+ }
439
+ }
440
+ /** Last `lines` rows across components, oldest first, rotations included. */
441
+ export function readRecentCrashLogs(components = CRASH_LOG_COMPONENTS, lines = 50, env = process.env) {
442
+ const rows = components.flatMap((component) => {
443
+ const primary = resolveCrashLogPath(component, env);
444
+ return [...readCrashLog(component, `${primary}.1`), ...readCrashLog(component, primary)];
445
+ });
446
+ rows.sort((a, b) => (a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0));
447
+ return rows.slice(Math.max(0, rows.length - Math.max(1, lines)));
448
+ }
449
+ /** Max chars of `detail`/`error` shown on one human `h2a logs` line. */
450
+ export const CRASH_LOG_HUMAN_DETAIL_MAX = 300;
451
+ function singleLine(text, max = CRASH_LOG_HUMAN_DETAIL_MAX) {
452
+ const flat = text.replace(/[\r\n]+/g, " ").trim();
453
+ return flat.length > max ? `${flat.slice(0, max)}…` : flat;
454
+ }
455
+ /**
456
+ * One human `h2a logs` line: what (event/reason/code/kind/errno), when
457
+ * (timestamp), where (component/session/pid/generation), why
458
+ * (detail/error, single-line and bounded). Detail is safe to show: rows are
459
+ * redacted before serialization.
460
+ */
461
+ export function formatCrashLogHumanRow(record) {
462
+ const parts = [
463
+ String(record["timestamp"] ?? "unknown"),
464
+ String(record["component"] ?? "?"),
465
+ String(record["event"] ?? "?"),
466
+ ];
467
+ for (const key of ["sessionId", "instanceId", "reason", "exitCode", "signal", "cause", "code", "kind", "errno", "generation", "version", "pid"]) {
468
+ if (record[key] !== undefined)
469
+ parts.push(`${key}=${String(record[key])}`);
470
+ }
471
+ if (typeof record["detail"] === "string" && record["detail"].length > 0) {
472
+ parts.push(`detail=${singleLine(record["detail"])}`);
473
+ }
474
+ if (typeof record["error"] === "string" && record["error"].length > 0) {
475
+ parts.push(`error=${singleLine(record["error"])}`);
476
+ }
477
+ return parts.join(" ");
478
+ }
479
+ /** Max bytes scanned from the end of a raw log for the viewer. */
480
+ export const CRASH_LOG_TAIL_MAX_BYTES = 256 * 1024;
481
+ /**
482
+ * Last `maxLines` of a text file for the viewer; missing/unreadable → [].
483
+ * Scans a bounded window from the end with positional reads — a multi-MB
484
+ * server dump is never loaded whole. Lines past the window are dropped whole
485
+ * (the leading, possibly partial, line is never shown truncated).
486
+ */
487
+ export function readFileTailLines(path, maxLines) {
488
+ let fd;
489
+ try {
490
+ fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
491
+ if (!fstatSync(fd).isFile())
492
+ return [];
493
+ const size = fstatSync(fd).size;
494
+ if (size === 0)
495
+ return [];
496
+ const want = Math.min(size, CRASH_LOG_TAIL_MAX_BYTES);
497
+ const start = size - want;
498
+ const buffer = Buffer.alloc(want);
499
+ let bytesRead = 0;
500
+ while (bytesRead < want) {
501
+ const read = readSync(fd, buffer, bytesRead, want - bytesRead, start + bytesRead);
502
+ if (read <= 0)
503
+ break;
504
+ bytesRead += read;
505
+ }
506
+ const lines = buffer.subarray(0, bytesRead).toString("utf8").split("\n");
507
+ while (lines.length > 0 && lines[lines.length - 1] === "")
508
+ lines.pop();
509
+ if (start > 0)
510
+ lines.shift();
511
+ return lines.slice(Math.max(0, lines.length - Math.max(1, maxLines)));
512
+ }
513
+ catch {
514
+ return [];
515
+ }
516
+ finally {
517
+ if (fd !== undefined) {
518
+ try {
519
+ closeSync(fd);
520
+ }
521
+ catch {
522
+ /* A tail read never escapes. */
523
+ }
524
+ }
525
+ }
526
+ }
527
+ /**
528
+ * Passive fatal-path witness for short-lived launcher-side processes (the CLI
529
+ * launcher, the op child). `uncaughtExceptionMonitor` observes without
530
+ * altering Node's default crash/exit behavior: it only leaves a row behind in
531
+ * `component`.log so `h2a logs` can explain the crash. Never throws.
532
+ */
533
+ export function installCrashHandlers(component) {
534
+ process.on("uncaughtExceptionMonitor", (error, origin) => {
535
+ try {
536
+ appendCrashLog(component, {
537
+ event: origin === "unhandledRejection" ? "unhandledRejection" : "uncaughtException",
538
+ detail: error instanceof Error ? error.message : String(error),
539
+ });
540
+ }
541
+ catch {
542
+ /* A witness never breaks the fatal path it documents. */
543
+ }
544
+ });
545
+ }
546
+ let cliWitnessInstalled = false;
547
+ /**
548
+ * Idempotent CLI fatal-path witness. The owner binary (core `bin.ts`) reaches
549
+ * the runtime through lazy `dispatchRuntime()` → `main()`, never with the
550
+ * runtime file as `argv[1]` — so an `isEntryPoint()` gate alone never fires
551
+ * on the real path. Installing here covers every dispatch; the once-guard
552
+ * keeps repeated `main()` calls (and tests) to a single listener.
553
+ */
554
+ export function installCliWitnessOnce() {
555
+ if (cliWitnessInstalled)
556
+ return;
557
+ cliWitnessInstalled = true;
558
+ installCrashHandlers("cli");
559
+ }
560
+ //# sourceMappingURL=crash-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crash-log.js","sourceRoot":"","sources":["../src/crash-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { CloneIdentityDto, WorkspaceDeclarationDto, WorktreeIdentityDto } from "../vendor/engram-live/contracts.js";
2
+ export declare const LIVE_DECLARATION_KIND = "h2a-live-declaration";
3
+ export declare const LIVE_DECLARATION_SCHEMA_VERSION = 1;
4
+ /**
5
+ * Typed revision conflict: the durable declaration moved (or vanished)
6
+ * under a writer holding a stale base revision. The message keeps the
7
+ * `revision_conflict` marker; the name and the revision fields let callers
8
+ * branch on it without parsing text.
9
+ */
10
+ export declare class LiveRevisionConflict extends Error {
11
+ readonly declarationId: string;
12
+ readonly expectedDeclarationRevision: number;
13
+ /** Current durable revision; undefined when the declaration is gone. */
14
+ readonly actualDeclarationRevision: number | undefined;
15
+ constructor(declarationId: string, expectedDeclarationRevision: number, actualDeclarationRevision: number | undefined);
16
+ }
17
+ export interface LiveDeclarationRecord {
18
+ readonly kind: typeof LIVE_DECLARATION_KIND;
19
+ readonly schemaVersion: typeof LIVE_DECLARATION_SCHEMA_VERSION;
20
+ /** The exact neutral DTO; validated with validateWorkspaceDeclaration on every write. */
21
+ readonly declaration: WorkspaceDeclarationDto;
22
+ /** Full local clone identity (commonDirRealpath stays host-local; only cloneId is shared). */
23
+ readonly clone: CloneIdentityDto;
24
+ /** Full local worktree identity. */
25
+ readonly worktree: WorktreeIdentityDto;
26
+ readonly createdAt: string;
27
+ /** Activation timestamp; replay after restart never renews it. */
28
+ readonly activatedAt: string;
29
+ readonly updatedAt: string;
30
+ }
31
+ /** Durable declarations live under the injected h2a root, never a worktree. */
32
+ export declare function liveDeclarationsPath(root: string): string;
33
+ export interface LiveDeclarationStore {
34
+ /** All durable declarations, deterministically ordered. */
35
+ list(): readonly LiveDeclarationRecord[];
36
+ get(declarationId: string): LiveDeclarationRecord | undefined;
37
+ /** First declaration whose authorized root covers `path`. */
38
+ findByPath(path: string): LiveDeclarationRecord | undefined;
39
+ insert(record: LiveDeclarationRecord): void;
40
+ /**
41
+ * Revision-guarded mutation: re-reads the durable store, refuses a stale
42
+ * `expectedDeclarationRevision` with `revision_conflict`, verifies the
43
+ * composed next record (declarationRevision exactly + 1, immutable
44
+ * identity triangle, binding renewal-or-preserved with first binding
45
+ * exactly INITIAL_BINDING_REVISION then strictly greater, valid DTOs)
46
+ * and persists atomically. The callback returns the fully composed next
47
+ * record; the store owns the guard, never silent arithmetic.
48
+ */
49
+ update(declarationId: string, expectedDeclarationRevision: number, mutate: (record: LiveDeclarationRecord) => LiveDeclarationRecord): LiveDeclarationRecord;
50
+ remove(declarationId: string): boolean;
51
+ }
52
+ /**
53
+ * A store instance is a thin read-through over the durable file: every
54
+ * operation re-reads, so two instances (or two processes) on the same root
55
+ * observe each other's committed writes.
56
+ */
57
+ export declare function createLiveDeclarationStore(root: string): LiveDeclarationStore;
58
+ //# sourceMappingURL=live-declarations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-declarations.d.ts","sourceRoot":"","sources":["../../src/gateway-host/live-declarations.ts"],"names":[],"mappings":"AAwDA,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,oCAAoC,CAAC;AAE5C,eAAO,MAAM,qBAAqB,yBAAyB,CAAC;AAC5D,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,wEAAwE;IACxE,QAAQ,CAAC,yBAAyB,EAAE,MAAM,GAAG,SAAS,CAAC;gBAGrD,aAAa,EAAE,MAAM,EACrB,2BAA2B,EAAE,MAAM,EACnC,yBAAyB,EAAE,MAAM,GAAG,SAAS;CAahD;AAgHD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,OAAO,qBAAqB,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,OAAO,+BAA+B,CAAC;IAC/D,yFAAyF;IACzF,QAAQ,CAAC,WAAW,EAAE,uBAAuB,CAAC;IAC9C,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAkED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AA4CD,MAAM,WAAW,oBAAoB;IACnC,2DAA2D;IAC3D,IAAI,IAAI,SAAS,qBAAqB,EAAE,CAAC;IACzC,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAC;IAC9D,6DAA6D;IAC7D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAC;IAC5D,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC5C;;;;;;;;OAQG;IACH,MAAM,CACJ,aAAa,EAAE,MAAM,EACrB,2BAA2B,EAAE,MAAM,EACnC,MAAM,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,qBAAqB,GAC/D,qBAAqB,CAAC;IACzB,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAmN7E"}