claude-nomad 0.26.2 → 0.28.0

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.
package/src/summary.ts CHANGED
@@ -1,51 +1,99 @@
1
+ import { green, okGlyph, warnGlyph, yellow } from './color.ts';
1
2
  import { ok, warn } from './utils.ts';
2
3
 
3
4
  /**
4
- * Emit the single end-of-run summary line shared by cmdPull, cmdPush, and
5
- * cmdDiff. Canonical phrasing:
5
+ * Pure phrasing core for the end-of-run summary line shared by cmdPull,
6
+ * cmdPush, and cmdDiff. Returns the message `text` (without any status glyph)
7
+ * plus a `clean` flag so callers can pick the right glyph/stream. Canonical
8
+ * phrasing:
6
9
  * - `summary: clean` when nothing was unmapped (and, for push, no
7
- * collisions or extras skipped). Always printed so users see a consistent
8
- * terminator and can spot when behavior changes.
10
+ * collisions or extras skipped).
9
11
  * - `summary: <N> unmapped on pull (run nomad doctor to list)`
10
12
  * - `summary: <N> unmapped on pull, <X> extras skipped (run nomad doctor to list)`
11
13
  * - `summary: <N> unmapped on diff (run nomad doctor to list)`
12
14
  * - `summary: <N> unmapped on push, <M> collisions (run nomad doctor to list)`
13
15
  * - `summary: <N> unmapped on push, <M> collisions, <X> extras skipped (run nomad doctor to list)`
14
16
  *
15
- * Clean outcomes go through `ok()` (green `✓` glyph, stdout) and unmapped /
16
- * collision / extras-skipped outcomes go through `warn()` (yellow `⚠︎` glyph,
17
- * stderr). The status glyph carries the success/warn semantics; users see e.g.
18
- * `✓ summary: clean` or `⚠︎ summary: 3 unmapped on pull (...)`. Note: clean
19
- * still goes to stdout so it survives backgrounded shell-rc invocations
20
- * like `nomad pull 2>/dev/null &`. `collisions` is meaningful only for
21
- * `'push'`; for `'pull'` / `'diff'` it is ignored and defaults to 0.
22
- * `extrasSkipped` counts dirnames that the per-project whitelist
23
- * (`SUPPORTED_EXTRAS`) declined to sync; surfaces from `remapExtrasPush`
24
- * and `remapExtrasPull`. The fourth positional parameter defaults to 0 so
25
- * legacy three-arg call sites continue to work unchanged (D-03 additive
26
- * contract). This module is the SINGLE source of truth for the phrasing,
27
- * eliminating drift risk across the three callers by construction.
17
+ * `collisions` is meaningful only for `'push'`; for `'pull'` / `'diff'` it is
18
+ * ignored and defaults to 0. `extrasSkipped` counts dirnames that the
19
+ * per-project whitelist (`SUPPORTED_EXTRAS`) declined to sync. This function is
20
+ * the SINGLE source of truth for the phrasing, so `emitSummary` (standalone
21
+ * line) and `summaryRow` (tree row) cannot drift apart.
22
+ *
23
+ * @param verb - the originating command.
24
+ * @param unmapped - count of path-map entries skipped for this host.
25
+ * @param collisions - push-only collision count (ignored for pull/diff).
26
+ * @param extrasSkipped - count of extras dirnames the whitelist declined.
27
+ * @returns `{ text, clean }` where `clean` is true on the no-warning outcome.
28
28
  */
29
- export function emitSummary(
29
+ export function summaryText(
30
30
  verb: 'pull' | 'push' | 'diff',
31
31
  unmapped: number,
32
32
  collisions = 0,
33
33
  extrasSkipped = 0,
34
- ): void {
34
+ ): { text: string; clean: boolean } {
35
+ const extras = extrasSkipped > 0 ? `, ${extrasSkipped} extras skipped` : '';
35
36
  if (verb === 'push') {
36
37
  if (unmapped === 0 && collisions === 0 && extrasSkipped === 0) {
37
- ok('summary: clean');
38
- return;
38
+ return { text: 'summary: clean', clean: true };
39
39
  }
40
40
  const base = `summary: ${unmapped} unmapped on push, ${collisions} collisions`;
41
- const extras = extrasSkipped > 0 ? `, ${extrasSkipped} extras skipped` : '';
42
- warn(`${base}${extras} (run nomad doctor to list)`);
43
- return;
41
+ return { text: `${base}${extras} (run nomad doctor to list)`, clean: false };
44
42
  }
45
43
  if (unmapped === 0 && extrasSkipped === 0) {
46
- ok('summary: clean');
44
+ return { text: 'summary: clean', clean: true };
45
+ }
46
+ return {
47
+ text: `summary: ${unmapped} unmapped on ${verb}${extras} (run nomad doctor to list)`,
48
+ clean: false,
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Build the fully-rendered Summary-section row (status glyph embedded) for the
54
+ * grouped push/pull tree. Delegates phrasing to `summaryText` so the row text
55
+ * matches `emitSummary` byte-for-byte. A clean outcome renders
56
+ * `${green(okGlyph)} <text>`; any warning outcome renders
57
+ * `${yellow(warnGlyph)} <text>`.
58
+ *
59
+ * @param verb - the originating command.
60
+ * @param unmapped - count of path-map entries skipped for this host.
61
+ * @param collisions - push-only collision count (ignored for pull/diff).
62
+ * @param extrasSkipped - count of extras dirnames the whitelist declined.
63
+ * @returns the rendered row string for the Summary section.
64
+ */
65
+ export function summaryRow(
66
+ verb: 'pull' | 'push' | 'diff',
67
+ unmapped: number,
68
+ collisions = 0,
69
+ extrasSkipped = 0,
70
+ ): string {
71
+ const { text, clean } = summaryText(verb, unmapped, collisions, extrasSkipped);
72
+ return clean ? `${green(okGlyph)} ${text}` : `${yellow(warnGlyph)} ${text}`;
73
+ }
74
+
75
+ /**
76
+ * Emit the single end-of-run summary line shared by cmdPull, cmdPush, and
77
+ * cmdDiff. Delegates phrasing to `summaryText` so the wording cannot drift from
78
+ * `summaryRow`. Clean outcomes go through `ok()` (green `✓` glyph, stdout) and
79
+ * unmapped / collision / extras-skipped outcomes go through `warn()` (yellow
80
+ * `⚠︎` glyph, stderr). The status glyph carries the success/warn semantics;
81
+ * users see e.g. `✓ summary: clean` or `⚠︎ summary: 3 unmapped on pull (...)`.
82
+ * Clean still goes to stdout so it survives backgrounded shell-rc invocations
83
+ * like `nomad pull 2>/dev/null &`. The fourth positional parameter defaults to
84
+ * 0 so legacy three-arg call sites continue to work unchanged (D-03 additive
85
+ * contract). `cmdDiff` still calls this for its standalone summary line.
86
+ */
87
+ export function emitSummary(
88
+ verb: 'pull' | 'push' | 'diff',
89
+ unmapped: number,
90
+ collisions = 0,
91
+ extrasSkipped = 0,
92
+ ): void {
93
+ const { text, clean } = summaryText(verb, unmapped, collisions, extrasSkipped);
94
+ if (clean) {
95
+ ok(text);
47
96
  return;
48
97
  }
49
- const extras = extrasSkipped > 0 ? `, ${extrasSkipped} extras skipped` : '';
50
- warn(`summary: ${unmapped} unmapped on ${verb}${extras} (run nomad doctor to list)`);
98
+ warn(text);
51
99
  }