@bli-cockpit/cli 0.2.65 → 0.2.66

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.
@@ -15,7 +15,7 @@ export async function runCockpitCli(argv, io) {
15
15
  }
16
16
 
17
17
  if (command === "--version" || command === "-V" || command === "version") {
18
- writeLine(io?.stdout ?? process.stdout, "0.2.65");
18
+ writeLine(io?.stdout ?? process.stdout, "0.2.66");
19
19
  return 0;
20
20
  }
21
21
 
@@ -8,6 +8,11 @@
8
8
  * pastes into Slack when something looks wrong. The `--json` payload is the
9
9
  * machine contract and is byte-for-byte unchanged — `status-json-shape.test.ts`
10
10
  * holds it to that.
11
+ *
12
+ * Two branches, one machine: a folder holding several repos prints a row each,
13
+ * a single repo prints the full block, and BOTH carry the setup receipt
14
+ * (BLI-3789) — it says whether this HOST is connected, which does not change
15
+ * with the folder you are standing in.
11
16
  */
12
17
  import { readdir, stat } from "node:fs/promises";
13
18
  import os from "node:os";
@@ -24,6 +29,18 @@ import { getCollectorRuntimePaths, inspectLocalCollectorStatus, readLocalCollect
24
29
  import { normalizeCollectionRoots } from "../root-normalization.js";
25
30
  export async function runStatus(command, io) {
26
31
  const backfillCursor = await inspectBackfillCursor(command.homeDir);
32
+ // BLI-3731: "is this machine actually connected?" belongs beside "is it
33
+ // collecting?", and it is read back off the host rather than remembered.
34
+ // Refreshing here also keeps the heartbeat's cache warm without the 15-minute
35
+ // tick paying for the probe.
36
+ //
37
+ // BLI-3789: read it BEFORE the branch below, not after. The receipt is a fact
38
+ // about the MACHINE, so it cannot depend on whether the folder you happen to
39
+ // stand in holds one repo or six — and the multi-repo branch, which every
40
+ // agent machine takes, used to return before the receipt was ever built.
41
+ const setupReceipt = await refreshSetupReceipt(io, {
42
+ ...(command.homeDir ? { homeDir: command.homeDir } : {}),
43
+ });
27
44
  const worktrees = await discoverCommandWorktrees(command.repoRoot, { maxDepth: command.maxDepth, maxRepos: command.maxRepos, homeDir: command.homeDir }, io);
28
45
  if (worktrees.length > 1) {
29
46
  const statuses = await Promise.all(worktrees.map(async (worktree) => ({
@@ -34,7 +51,17 @@ export async function runStatus(command, io) {
34
51
  head_sha: worktree.head_sha,
35
52
  })));
36
53
  if (command.json) {
37
- writeLine(io.stdout, JSON.stringify({ mode: "multi_repo", statuses, backfill_cursor: backfillCursor }, null, 2));
54
+ writeLine(io.stdout, JSON.stringify({
55
+ mode: "multi_repo",
56
+ statuses,
57
+ backfill_cursor: backfillCursor,
58
+ // Beside `backfill_cursor`, and for the same reason: both are facts
59
+ // about this machine, so both sit at the top of the payload rather
60
+ // than once per repo row. Null means this run could not read the
61
+ // host — `refreshSetupReceipt` named the reason on stderr — never
62
+ // "this machine is not connected".
63
+ setup_receipt: setupReceipt?.receipt ?? null,
64
+ }, null, 2));
38
65
  return 0;
39
66
  }
40
67
  writeLine(io.stdout, "Tower status — every repo below this folder");
@@ -42,16 +69,10 @@ export async function runStatus(command, io) {
42
69
  for (const status of statuses) {
43
70
  writeLine(io.stdout, `- ${status.repo_label ?? status.repo}/${status.worktree_label ?? "worktree"} · ${status.branch} · head:${shortSha(status.head_sha)} · ${status.upload_state}`);
44
71
  }
72
+ writeConnectedBlock(io, setupReceipt);
45
73
  return 0;
46
74
  }
47
75
  const status = await inspectLocalCollectorStatus(command);
48
- // BLI-3731: "is this machine actually connected?" belongs beside "is it
49
- // collecting?", and it is read back off the host rather than remembered.
50
- // Refreshing here also keeps the heartbeat's cache warm without the 15-minute
51
- // tick paying for the probe.
52
- const setupReceipt = await refreshSetupReceipt(io, {
53
- ...(command.homeDir ? { homeDir: command.homeDir } : {}),
54
- });
55
76
  if (command.json) {
56
77
  writeLine(io.stdout, JSON.stringify({
57
78
  ...status,
@@ -88,13 +109,22 @@ export async function runStatus(command, io) {
88
109
  writeLine(io.stdout, `Stuck files: ${stuckEvidenceLine(status)}`);
89
110
  for (const detail of status.details)
90
111
  writeLine(io.stdout, `- ${detail}`);
112
+ writeConnectedBlock(io, setupReceipt);
113
+ return 0;
114
+ }
115
+ /**
116
+ * The receipt block, in the words `cockpit doctor` prints, from the one reader
117
+ * (BLI-3789). Both branches of `status` call this: a person standing in a
118
+ * parent folder is asking about the same machine as a person standing in one
119
+ * repo, and only one of them used to be told.
120
+ */
121
+ function writeConnectedBlock(io, setupReceipt) {
91
122
  writeLine(io.stdout, "Connected:");
92
123
  for (const line of setupReceipt
93
124
  ? setupReceiptBlock(setupReceipt, { indent: " " })
94
125
  : [" unknown — run `cockpit doctor` to read this machine."]) {
95
126
  writeLine(io.stdout, line);
96
127
  }
97
- return 0;
98
128
  }
99
129
  /**
100
130
  * Done, still working, or never started — and when it is still working, how
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/cli",
3
- "version": "0.2.65",
3
+ "version": "0.2.66",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {