@sealant/mend 0.36.0-next.665 → 0.36.0-next.684

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 (95) hide show
  1. package/README.md +19 -0
  2. package/dist/{chunk-K5WNRH4V.js → chunk-DHM7VXTR.js} +119 -14
  3. package/dist/{dashboard-DQB5RNXJ.js → dashboard-OBFWHSPD.js} +8 -2
  4. package/dist/main.js +1620 -206
  5. package/man/mend-accounts.1 +1 -1
  6. package/man/mend-adopt.1 +1 -1
  7. package/man/mend-attach.1 +1 -1
  8. package/man/mend-codex.1 +1 -1
  9. package/man/mend-completions.1 +1 -1
  10. package/man/mend-connect-pi.1 +1 -1
  11. package/man/mend-connect.1 +1 -1
  12. package/man/mend-continue.1 +1 -1
  13. package/man/mend-doctor.1 +1 -1
  14. package/man/mend-dotfiles-repo.1 +1 -1
  15. package/man/mend-dotfiles-sync.1 +1 -1
  16. package/man/mend-dotfiles.1 +1 -1
  17. package/man/mend-env-cluster.1 +1 -1
  18. package/man/mend-env-load.1 +1 -1
  19. package/man/mend-env-show.1 +1 -1
  20. package/man/mend-folder-create.1 +1 -1
  21. package/man/mend-folder-list.1 +1 -1
  22. package/man/mend-folder-push.1 +1 -1
  23. package/man/mend-folder-rm.1 +1 -1
  24. package/man/mend-git-author.1 +1 -1
  25. package/man/mend-help.1 +1 -1
  26. package/man/mend-invite.1 +1 -1
  27. package/man/mend-keys-init.1 +1 -1
  28. package/man/mend-keys-mode.1 +1 -1
  29. package/man/mend-keys-share.1 +1 -1
  30. package/man/mend-keys-show.1 +1 -1
  31. package/man/mend-land.1 +1 -1
  32. package/man/mend-login.1 +1 -1
  33. package/man/mend-logout.1 +1 -1
  34. package/man/mend-logs.1 +13 -2
  35. package/man/mend-man.1 +1 -1
  36. package/man/mend-members.1 +1 -1
  37. package/man/mend-memory-import.1 +1 -1
  38. package/man/mend-memory-rm.1 +1 -1
  39. package/man/mend-memory-show.1 +1 -1
  40. package/man/mend-memory.1 +1 -1
  41. package/man/mend-models.1 +1 -1
  42. package/man/mend-operator-exposure.1 +1 -1
  43. package/man/mend-operator-gate.1 +1 -1
  44. package/man/mend-operator-grant-owner.1 +1 -1
  45. package/man/mend-operator-org-create.1 +1 -1
  46. package/man/mend-operator-org-invite-owner.1 +1 -1
  47. package/man/mend-operator-org-list.1 +1 -1
  48. package/man/mend-operator-org-rename.1 +1 -1
  49. package/man/mend-operator-reset-link.1 +1 -1
  50. package/man/mend-pair.1 +1 -1
  51. package/man/mend-projects.1 +1 -1
  52. package/man/mend-pull.1 +1 -1
  53. package/man/mend-refresh.1 +1 -1
  54. package/man/mend-rejoin.1 +1 -1
  55. package/man/mend-resume.1 +1 -1
  56. package/man/mend-run.1 +2 -2
  57. package/man/mend-secrets-add.1 +1 -1
  58. package/man/mend-secrets-rm.1 +1 -1
  59. package/man/mend-secrets.1 +1 -1
  60. package/man/mend-server-logs.1 +1 -1
  61. package/man/mend-server-restart.1 +1 -1
  62. package/man/mend-server-setup.1 +32 -2
  63. package/man/mend-server-start.1 +1 -1
  64. package/man/mend-server-status.1 +4 -2
  65. package/man/mend-server-stop.1 +2 -2
  66. package/man/mend-server-upgrade.1 +1 -1
  67. package/man/mend-server.1 +1 -1
  68. package/man/mend-service-add.1 +1 -1
  69. package/man/mend-service-connect.1 +1 -1
  70. package/man/mend-service-init.1 +1 -1
  71. package/man/mend-service-list.1 +10 -4
  72. package/man/mend-service-logs.1 +1 -1
  73. package/man/mend-service-restart.1 +1 -1
  74. package/man/mend-service-run.1 +13 -6
  75. package/man/mend-service-stop.1 +1 -1
  76. package/man/mend-session-share.1 +1 -1
  77. package/man/mend-sessions.1 +1 -1
  78. package/man/mend-shell.1 +1 -1
  79. package/man/mend-skills-push.1 +1 -1
  80. package/man/mend-skills.1 +1 -1
  81. package/man/mend-snake.1 +1 -1
  82. package/man/mend-ssh-keys-remove.1 +18 -0
  83. package/man/mend-ssh-keys.1 +15 -0
  84. package/man/mend-ssh-setup.1 +2 -2
  85. package/man/mend-ssh.1 +2 -2
  86. package/man/mend-stop.1 +1 -1
  87. package/man/mend-ui.1 +1 -1
  88. package/man/mend-uninstall.1 +2 -2
  89. package/man/mend-version.1 +1 -1
  90. package/man/mend-wait.1 +5 -5
  91. package/man/mend-workspace-replace.1 +1 -1
  92. package/man/mend-worktrees-rm.1 +1 -1
  93. package/man/mend-worktrees.1 +1 -1
  94. package/man/mend.1 +10 -4
  95. package/package.json +2 -2
package/README.md CHANGED
@@ -243,6 +243,8 @@ mend ssh # inspect config and this client's key registr
243
243
  mend ssh setup # register a key and reconcile this server's Host block
244
244
  mend ssh setup --key ./my-key # explicitly select private key or its .pub file
245
245
  mend ssh setup --host mend.example.com
246
+ mend ssh keys # your registered keys, from every machine; this one is marked
247
+ mend ssh keys remove SHA256:… # stop the gateway accepting one of them
246
248
  ```
247
249
 
248
250
  Setup puts the managed block before wildcard defaults and restores all-host scope before your
@@ -263,6 +265,23 @@ Status and setup report config and client-key registration, not a successful SSH
263
265
  verified host trust. The public Sealant SDK's gateway info supplies host, port and username prefix,
264
266
  not a host-key fingerprint. Mend cannot authenticate a rotated host key from that metadata.
265
267
 
268
+ ### Removing a key
269
+
270
+ `mend ssh keys` lists every key your account registered, with its fingerprint, name, algorithm and
271
+ the day it was registered; `--json` prints the same with `thisMachine` on each. The platform does
272
+ not record when a key was last used. `mend ssh keys remove <fingerprint>` removes one of your own
273
+ keys; another person's fingerprint answers as an unknown one. The gateway looks a key up on every
274
+ new connection, so the next connection offering it is refused. A connection already open stays open
275
+ until it ends. The key file and this server's `~/.ssh/config` block stay on the machine that
276
+ registered it; `mend ssh setup` there registers it again.
277
+
278
+ `mend uninstall --home` removes the key this machine registered before it revokes the terminal's
279
+ device token, then deletes the key file and the managed block. The key is found by its public half,
280
+ so an encrypted private key or a stopped agent does not hide it. When the server refuses the
281
+ removal, or this machine's public key cannot be read, the uninstall still finishes and exits 1,
282
+ naming the fingerprint that may still be registered and `mend ssh keys remove` to run from another
283
+ signed-in machine.
284
+
266
285
  ### Gateway host-key rotation
267
286
 
268
287
  Mend uses a stable per-server `HostKeyAlias`. OpenSSH's `accept-new` policy accepts an unknown key
@@ -26465,6 +26465,68 @@ var AuditEventId = Schema_exports.String.pipe(Schema_exports.brand("AuditEventId
26465
26465
  var SessionControlEventId = Schema_exports.String.pipe(Schema_exports.brand("SessionControlEventId"));
26466
26466
  var ChangeLandingId = Schema_exports.String.pipe(Schema_exports.brand("ChangeLandingId"));
26467
26467
 
26468
+ // ../../packages/domain/src/repository-url.ts
26469
+ var isSshScheme = (scheme) => /^(?:git\+)?ssh(?:\+git)?$/i.test(scheme);
26470
+ var authorityEnd = (text, from) => {
26471
+ const rest = text.slice(from).search(/[/?#]/u);
26472
+ return rest === -1 ? text.length : from + rest;
26473
+ };
26474
+ var keptUserinfo = (scheme, userinfo) => {
26475
+ if (!isSshScheme(scheme)) return "";
26476
+ const user = userinfo.split(":")[0] ?? "";
26477
+ return user === "" || user.includes("@") ? "" : `${user}@`;
26478
+ };
26479
+ var isSchemeChar = (char) => /[a-z0-9+.-]/iu.test(char);
26480
+ var schemeBefore = (text, separator, floor2) => {
26481
+ let start = separator;
26482
+ while (start > floor2 && isSchemeChar(text.charAt(start - 1))) start -= 1;
26483
+ while (start < separator && !/[a-z]/iu.test(text.charAt(start))) start += 1;
26484
+ return start < separator ? text.slice(start, separator) : null;
26485
+ };
26486
+ var redact4 = (text) => {
26487
+ let out = "";
26488
+ let copied = 0;
26489
+ let floor2 = 0;
26490
+ for (let separator = text.indexOf("://"); separator !== -1; ) {
26491
+ const authorityStart = separator + 3;
26492
+ const scheme = schemeBefore(text, separator, floor2);
26493
+ if (scheme !== null) {
26494
+ const authority = text.slice(authorityStart, authorityEnd(text, authorityStart));
26495
+ const at = authority.lastIndexOf("@");
26496
+ if (at !== -1) {
26497
+ const userinfo = authority.slice(0, at);
26498
+ const kept = keptUserinfo(scheme, userinfo);
26499
+ if (kept !== `${userinfo}@`) {
26500
+ out += `${text.slice(copied, authorityStart)}${kept}`;
26501
+ copied = authorityStart + at + 1;
26502
+ }
26503
+ }
26504
+ }
26505
+ floor2 = authorityStart;
26506
+ separator = text.indexOf("://", authorityStart);
26507
+ }
26508
+ return copied === 0 ? text : out + text.slice(copied);
26509
+ };
26510
+ var parsedCredential = (url) => {
26511
+ if (!URL.canParse(url)) return false;
26512
+ const parsed = new URL(url);
26513
+ const scheme = parsed.protocol.slice(0, -1);
26514
+ return parsed.password !== "" || parsed.username !== "" && !isSshScheme(scheme);
26515
+ };
26516
+ var clearedByParser = (url) => {
26517
+ const parsed = new URL(url);
26518
+ parsed.password = "";
26519
+ if (!isSshScheme(parsed.protocol.slice(0, -1))) parsed.username = "";
26520
+ return parsed.toString();
26521
+ };
26522
+ var redactUrlCredentials = (text) => redact4(text);
26523
+ var redactRepositoryUrl = (url) => {
26524
+ const scanned = redact4(url);
26525
+ return parsedCredential(scanned) ? clearedByParser(scanned) : scanned;
26526
+ };
26527
+ var repositoryUrlHasCredential = (url) => redactRepositoryUrl(url) !== url || parsedCredential(url);
26528
+ var REPOSITORY_URL_CREDENTIAL_GUIDANCE = 'This URL carries a login or token before the "@". Mend shows a repository URL to everyone who can see the repository, so it never stores one. Use the SSH URL (git@host:owner/repo.git) with your Mend key (`mend keys` shows it), or your own key through the agent bridge (`--auth bridge`).';
26529
+
26468
26530
  // ../../packages/domain/src/settings.ts
26469
26531
  var PrMode = Schema_exports.Literals(["draft-immediately", "pr-on-approval"]);
26470
26532
  var onByDefault = Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(true)));
@@ -26692,6 +26754,7 @@ var repositoryCloneUrlIssue = (value3) => {
26692
26754
  !/^(?:[a-z0-9_-]+(?:\.[a-z0-9_-]+)*\.?|\[[0-9a-f:.]+\])$/i.test(url.hostname)) {
26693
26755
  return REPOSITORY_CLONE_URL_GUIDANCE;
26694
26756
  }
26757
+ if (repositoryUrlHasCredential(value3)) return REPOSITORY_URL_CREDENTIAL_GUIDANCE;
26695
26758
  return null;
26696
26759
  };
26697
26760
  var RepositoryCloneUrl = Schema_exports.String.pipe(
@@ -27163,7 +27226,14 @@ var AuditAction = Schema_exports.Literals([
27163
27226
  "change.pull_request_refreshed",
27164
27227
  "change.bundle_downloaded",
27165
27228
  // A pull request opened outside Mend was read with the owner's `gh` and recorded.
27166
- "change.pull_request_adopted"
27229
+ "change.pull_request_adopted",
27230
+ // docs/WORKSPACE-SSH.md: a key the workspace SSH gateway accepts for an account was registered,
27231
+ // or archived so the gateway refuses it. The subject is the member who holds the key.
27232
+ "ssh_key.added",
27233
+ "ssh_key.removed",
27234
+ // A member was removed and some of their keys are still active (or unread): Mend keeps trying,
27235
+ // and each key it archives later is its own `ssh_key.removed`.
27236
+ "ssh_key.revocation_pending"
27167
27237
  ]);
27168
27238
  var AuditData = Schema_exports.Record(
27169
27239
  Schema_exports.String,
@@ -27627,6 +27697,7 @@ var AgentEvent = Schema_exports.Union([
27627
27697
  var CaptureDrainReason = Schema_exports.Literals(["stop", "relaunch", "replacement"]);
27628
27698
  var FALLBACK_REPLACEMENT_AGE_SECONDS = 7 * 60 * 60 + 30 * 60;
27629
27699
  var CAPTURE_EXECUTOR_RETAINED = "retained";
27700
+ var CAPTURE_SEAL_UNRESTORABLE = "unrestorable";
27630
27701
  var CAPTURE_COMPLETION_UNREPORTED = "unreported";
27631
27702
  var captureDurationWords = (ms) => {
27632
27703
  const seconds2 = Math.max(0, Math.floor(ms / 1e3));
@@ -27686,6 +27757,8 @@ var captureIncompleteWords = (reason) => {
27686
27757
  return "executor error";
27687
27758
  case CAPTURE_EXECUTOR_RETAINED:
27688
27759
  return "executor kept for recovery";
27760
+ case CAPTURE_SEAL_UNRESTORABLE:
27761
+ return "final seal refused \xB7 git section failed verification";
27689
27762
  default:
27690
27763
  return reason;
27691
27764
  }
@@ -27788,6 +27861,18 @@ var CheckpointTrigger = Schema_exports.Literals([
27788
27861
  "review-open",
27789
27862
  "user-mark"
27790
27863
  ]);
27864
+ var CheckpointSourceKind = Schema_exports.Literals(["stop-final", "stop-reading"]);
27865
+ var CheckpointSource = class extends Schema_exports.Class("CheckpointSource")({
27866
+ kind: CheckpointSourceKind,
27867
+ captureN: Schema_exports.NullOr(Schema_exports.Int),
27868
+ observedAt: Timestamp
27869
+ }) {
27870
+ };
27871
+ var checkpointSourceWords = (source, at) => [
27872
+ source.kind === "stop-final" ? "from the Stop's final save" : "from a Stop reading that did not save",
27873
+ ...source.captureN === null ? [] : [`capture ${source.captureN}`],
27874
+ at
27875
+ ].join(" \xB7 ");
27791
27876
  var Checkpoint = class extends Schema_exports.Class("Checkpoint")({
27792
27877
  id: CheckpointId,
27793
27878
  worktreeId: WorktreeId,
@@ -27810,7 +27895,9 @@ var Checkpoint = class extends Schema_exports.Class("Checkpoint")({
27810
27895
  /** Record sequence the supervisor had seen when the snapshot was taken. */
27811
27896
  seq: SequenceNumber,
27812
27897
  trigger: CheckpointTrigger,
27813
- createdAt: Timestamp
27898
+ createdAt: Timestamp,
27899
+ /** Absent when the checkpoint observed the executor itself (`CheckpointSource`). */
27900
+ source: Schema_exports.optionalKey(CheckpointSource)
27814
27901
  }) {
27815
27902
  };
27816
27903
 
@@ -28384,6 +28471,7 @@ var HotWorkspaceEnvironment = Schema_exports.Struct({
28384
28471
  clusterBindingNames: Schema_exports.optional(Schema_exports.Array(Schema_exports.String)),
28385
28472
  clusterServiceAccount: Schema_exports.optional(Schema_exports.NullOr(Schema_exports.String))
28386
28473
  });
28474
+ var RemoteSsh = Schema_exports.Literals(["owner", "unbound", "not-taken"]);
28387
28475
  var HotWorkspace = class extends Schema_exports.Class("HotWorkspace")({
28388
28476
  id: SessionId,
28389
28477
  projectId: ProjectId,
@@ -28410,6 +28498,13 @@ var HotWorkspace = class extends Schema_exports.Class("HotWorkspace")({
28410
28498
  * `shared`.
28411
28499
  */
28412
28500
  harnessLayout: HarnessLayout,
28501
+ /**
28502
+ * Who Remote-SSH into the standby runs as (docs/adr/0016, decision 10), decided at its create and
28503
+ * kept for its claim: `owner` its owner's own user; `unbound` root, because Core could not bind
28504
+ * the owner's person; `not-taken` root, because Core runs no SSH session as a user. Rows from
28505
+ * before it are `not-taken`.
28506
+ */
28507
+ remoteSsh: RemoteSsh,
28413
28508
  /** Worktree directory name inside the project's store (derived from `id`). */
28414
28509
  worktree: Schema_exports.NullOr(Schema_exports.String),
28415
28510
  /** The pre-created session branch the worktree is on. */
@@ -28557,7 +28652,7 @@ var ProjectClusterBindingsSnapshot = class extends Schema_exports.Class(
28557
28652
  }) {
28558
28653
  };
28559
28654
 
28560
- // ../../node_modules/.pnpm/@sealant+api-contracts-next@0.39.0-next.707_effect@4.0.0-beta.93/node_modules/@sealant/api-contracts-next/dist/workspace-environment.js
28655
+ // ../../node_modules/.pnpm/@sealant+api-contracts-next@0.39.0-next.714_effect@4.0.0-beta.93/node_modules/@sealant/api-contracts-next/dist/workspace-environment.js
28561
28656
  var RESERVED_NAMES = new Map([
28562
28657
  // Identity/process roots the daemon and shells own.
28563
28658
  ...[
@@ -29026,6 +29121,7 @@ var ServiceView = class extends Schema_exports.Class("ServiceView")({
29026
29121
  previousEndpoints: Schema_exports.Array(ServiceEndpoint)
29027
29122
  }) {
29028
29123
  };
29124
+ var serviceStartCorrelation = (serviceId, startId) => `service-start:${serviceId}:${startId}`;
29029
29125
 
29030
29126
  // ../../packages/domain/src/workbench/session-control.ts
29031
29127
  var SessionControlKind = Schema_exports.Literals([
@@ -29634,17 +29730,23 @@ var pasteBytes = (text, bracketed) => Buffer.from(bracketed ? `\x1B[200~${text}\
29634
29730
  var firstPositional = (args2, valued) => args2.find(
29635
29731
  (argument, index2) => !argument.startsWith("--") && (index2 === 0 || !valued.includes(args2[index2 - 1] ?? ""))
29636
29732
  );
29637
- var redactCredentials = (text) => text.replace(
29638
- // Greedy up to the last `@` before the authority ends: a literal `@` in a password is userinfo.
29639
- /\b([a-z][a-z0-9+.-]*):\/\/([^/?#"<>`]*)@/giu,
29640
- (_whole, scheme, userinfo) => {
29641
- if (/^(git\+)?ssh$/iu.test(scheme)) {
29642
- const user = userinfo.split(":")[0] ?? "";
29643
- if (/^[a-z0-9._~-]+$/iu.test(user)) return `${scheme}://${user}@`;
29644
- }
29645
- return `${scheme}://`;
29646
- }
29647
- );
29733
+ var redactCredentials = (text) => redactUrlCredentials(text);
29734
+ var redactKeys = (field) => Object.fromEntries(Object.entries(field).map(([key, value3]) => [redactCredentials(key), value3]));
29735
+ var isPlainObject = (field) => typeof field === "object" && field !== null && (Object.getPrototypeOf(field) === Object.prototype || Object.getPrototypeOf(field) === null);
29736
+ var jsonWithoutCredentials = (value3) => {
29737
+ const printed = JSON.stringify(
29738
+ value3,
29739
+ (_key, field) => {
29740
+ if (typeof field === "string") return redactCredentials(field);
29741
+ if (Object.prototype.toString.call(field) === "[object String]") {
29742
+ return redactCredentials(String(field));
29743
+ }
29744
+ return isPlainObject(field) ? redactKeys(field) : field;
29745
+ },
29746
+ 2
29747
+ );
29748
+ return printed ?? "null";
29749
+ };
29648
29750
 
29649
29751
  // src/server-request.ts
29650
29752
  var MendRequestError = class extends Error {
@@ -29888,6 +29990,7 @@ export {
29888
29990
  AGENT_MEMORY_MAX_FILE_BYTES,
29889
29991
  AGENT_MEMORY_MAX_DATABASE_BYTES,
29890
29992
  agentMemoryNameOf,
29993
+ checkpointSourceWords,
29891
29994
  narrowCredential,
29892
29995
  claudeGrantFacts,
29893
29996
  sameGrant,
@@ -29904,6 +30007,7 @@ export {
29904
30007
  validatePiProfile,
29905
30008
  servicesHoldLine,
29906
30009
  validateSecretFilePath,
30010
+ serviceStartCorrelation,
29907
30011
  terminalReadOnlyLine,
29908
30012
  sharedControlLine,
29909
30013
  sharedControlConfirm,
@@ -29934,6 +30038,7 @@ export {
29934
30038
  pasteBytes,
29935
30039
  firstPositional,
29936
30040
  redactCredentials,
30041
+ jsonWithoutCredentials,
29937
30042
  MendRequestError,
29938
30043
  spoken,
29939
30044
  noAnswerError,
@@ -5,6 +5,7 @@ import {
5
5
  agentIsLive,
6
6
  agentOutcome,
7
7
  captureLineOf,
8
+ checkpointSourceWords,
8
9
  createSseParser,
9
10
  cwdFacts,
10
11
  eventFamilies,
@@ -23,7 +24,7 @@ import {
23
24
  workspaceReadsOf,
24
25
  worktreeJoinLine,
25
26
  wrapWords
26
- } from "./chunk-K5WNRH4V.js";
27
+ } from "./chunk-DHM7VXTR.js";
27
28
 
28
29
  // src/dashboard.tsx
29
30
  import { CliRenderEvents, createCliRenderer } from "@opentui/core";
@@ -1120,6 +1121,7 @@ var SYNTAX_FUNCTION = "#ffcd66";
1120
1121
 
1121
1122
  // src/review.tsx
1122
1123
  import { Fragment, jsx, jsxs } from "@opentui/react/jsx-runtime";
1124
+ var clockOf = (iso) => new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: false });
1123
1125
  var REVIEW_KEY = (changeId) => ["review", changeId];
1124
1126
  var EDITOR_KEY_BINDINGS = [{ name: "return", ctrl: true, action: "submit" }];
1125
1127
  var syntaxStyle = SyntaxStyle.fromStyles({
@@ -1165,6 +1167,7 @@ var fetchReview = async (ctx, changeId) => {
1165
1167
  sliceId: pinned.slice.id,
1166
1168
  checkpointAId: pinned.checkpointA.id,
1167
1169
  checkpointBId: pinned.checkpointB.id,
1170
+ checkpointSource: pinned.checkpointB.source ?? null,
1168
1171
  diffDigest: pinned.slice.diffDigest,
1169
1172
  anchorFiles: pinned.anchorFiles,
1170
1173
  files: buildReviewFiles(wire.diff, wire.files),
@@ -1998,7 +2001,10 @@ function ReviewScreen({
1998
2001
  session.id.slice(0, 8)
1999
2002
  ] }),
2000
2003
  isFetching ? /* @__PURE__ */ jsx("span", { fg: FAINT, children: " \xB7 syncing" }) : null,
2001
- /* @__PURE__ */ jsx("span", { fg: checkpointState === "failed" ? MUTED : FAINT, children: checkpointState === "recording" ? " \xB7 checkpointing" : checkpointState === "failed" ? " \xB7 checkpoint incomplete" : " \xB7 checkpoint recorded" })
2004
+ /* @__PURE__ */ jsx("span", { fg: checkpointState === "failed" ? MUTED : FAINT, children: checkpointState === "recording" ? " \xB7 checkpointing" : checkpointState === "failed" ? " \xB7 checkpoint incomplete" : data.checkpointSource === null ? " \xB7 checkpoint recorded" : ` \xB7 checkpoint ${checkpointSourceWords(
2005
+ data.checkpointSource,
2006
+ clockOf(data.checkpointSource.observedAt)
2007
+ )}` })
2002
2008
  ] }),
2003
2009
  /* @__PURE__ */ jsxs("text", { height: 1, bg: "transparent", children: [
2004
2010
  /* @__PURE__ */ jsxs("span", { fg: FAINT, children: [