acuvo-code 0.3.2 → 0.3.3

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/ENTERPRISE.md CHANGED
@@ -188,8 +188,8 @@ copy, but it *is* a place a process starts, and this is a list of those. Six and
188
188
  are the numbers to quote. Counting is the first thing a reviewer does.
189
189
 
190
190
  ⚠️ **This said "18 shipped files", then "41", then "90", then "101", then "108", and every
191
- one went stale in turn.** The package ships **118 files — 116 in `lib/`, 2 in
192
- `bin/` — about 77,339 lines**, with **233 test files** beside them (counted 2026-08-22).
191
+ one went stale in turn.** The package ships **119 files — 117 in `lib/`, 2 in
192
+ `bin/` — about 77552 lines**, with **234 test files** beside them (counted 2026-08-22).
193
193
 
194
194
  ⭐ **AND THE 108 WENT STALE IN THE MOST INSTRUCTIVE WAY POSSIBLE: THREE OF THE FILES IT
195
195
  MISSED WERE REACHABLE FROM NOTHING.** `wiring-reach.test.mjs` was naming
package/bin/acuvo.mjs CHANGED
@@ -1482,17 +1482,21 @@ ${formatBoard(listed)}
1482
1482
  }
1483
1483
  })();
1484
1484
 
1485
- const row = (k, v) => ` ${k.padEnd(11)}${v}`;
1486
- const banner = [
1487
- '',
1488
- ` ▌ACUVO CODE${pkgVersion ? ` ${pkgVersion}` : ''}`,
1489
- '',
1490
- row('workspace', shortenRoot(executor.root)),
1491
- row('model', config.model),
1492
- row('billing', billing),
1493
- row('can run', mode),
1494
- '',
1495
- ].join('\n');
1485
+ /**
1486
+ * ⚠️ `interactive: false` EVEN IN THE REPL, because `runChat` prints its own
1487
+ * "Type what you want done" line. Setting it here as well produced the
1488
+ * instruction twice, three lines apart — the banner owns the identity, the
1489
+ * chat loop owns the invitation, and neither should own both.
1490
+ */
1491
+ const { openingScreen } = await import('../lib/banner.mjs');
1492
+ const banner = openingScreen({
1493
+ version: pkgVersion,
1494
+ workspace: shortenRoot(executor.root),
1495
+ model: config.model,
1496
+ billing,
1497
+ canRun: mode,
1498
+ interactive: false,
1499
+ });
1496
1500
  if (opts.json) process.stderr.write(banner);
1497
1501
  else process.stdout.write(banner);
1498
1502
 
package/lib/banner.mjs ADDED
@@ -0,0 +1,97 @@
1
+ /**
2
+ * ── ⭐⭐⭐ WHAT YOU SEE WHEN YOU TYPE `acuvo` ────────────────────────────────
3
+ *
4
+ * Roman, 2026-08-22, having typed it: *"it's not opening as a typable terminal,
5
+ * with acuvo logo top left and details up top etc, like how claude code opens.
6
+ * have you actually designed the page?"*
7
+ *
8
+ * No — the previous version printed two dense lines of facts and a prompt. Every
9
+ * fact was correct and none of it was designed. This is the opening screen: a
10
+ * wordmark, one instruction, and the four things a person needs to know before
11
+ * they type anything.
12
+ *
13
+ * ── ⚠️ THE CONSTRAINTS THAT SHAPED IT, NOT PREFERENCES ──────────────────────
14
+ *
15
+ * · **Half-block glyphs only** (▀ ▄ █). Braille and fancy box-drawing render as
16
+ * tofu in cmd.exe and in a lot of CI log viewers, and a logo that renders as
17
+ * question marks is worse than no logo.
18
+ * · **No colour codes here.** The caller owns colour and already honours
19
+ * NO_COLOR; a module that hard-codes escapes produces garbage the moment its
20
+ * output is piped to a file.
21
+ * · **Every line under 80 columns**, because the narrowest terminal anyone
22
+ * actually uses is 80 and a wrapped banner looks broken rather than dense.
23
+ */
24
+
25
+ /**
26
+ * ACUVO in half-blocks. Three rows, because five is a splash screen — it belongs
27
+ * to something you open once a day, not something you run forty times.
28
+ */
29
+ const WORDMARK = [
30
+ '▄▀█ █▀▀ █ █ █ █ █▀█',
31
+ '█▀█ █▄▄ █▄█ ▀▄▀ █▄█',
32
+ ];
33
+
34
+ /**
35
+ * Build the opening screen.
36
+ *
37
+ * @param {object} o
38
+ * @param {string} o.version
39
+ * @param {string} o.workspace already shortened by the caller
40
+ * @param {string} o.model
41
+ * @param {string} o.billing who this run will charge
42
+ * @param {string} o.canRun what it may execute, or that it may not
43
+ * @param {boolean} [o.interactive] whether a prompt follows
44
+ * @returns {string}
45
+ */
46
+ export function openingScreen({ version, workspace, model, billing, canRun, interactive = false }) {
47
+ /**
48
+ * ── ⚠️⚠️ ELIDED, BECAUSE THE VALUES ARE NOT OURS ────────────────────────────
49
+ *
50
+ * Every value here arrives at runtime: a deep monorepo path, a long model id,
51
+ * the shell-mode warning. The first version of this function assumed they
52
+ * would be short and its own test caught it wrapping at 80 columns on
53
+ * perfectly ordinary inputs.
54
+ *
55
+ * ⭐ ELIDED IN THE MIDDLE, NOT THE END. The informative parts of a path are the
56
+ * drive and the leaf; chopping the tail leaves `C:\Users\somebody\Projects\a-`
57
+ * which identifies nothing. Same for a model id, where the family is at the
58
+ * front and the variant at the back.
59
+ */
60
+ const room = MAX_BANNER_COLUMNS - 2 - 11;
61
+ const fit = (v) => {
62
+ const s = String(v ?? '');
63
+ if (s.length <= room) return s;
64
+ const head = Math.ceil((room - 1) / 2);
65
+ const tail = room - 1 - head;
66
+ return `${s.slice(0, head)}…${s.slice(s.length - tail)}`;
67
+ };
68
+ const label = (k, v) => ` ${k.padEnd(11)}${fit(v)}`;
69
+ const lines = [
70
+ '',
71
+ ` ${WORDMARK[0]}`,
72
+ ` ${WORDMARK[1]} CODE${version ? ` ${version}` : ''}`,
73
+ '',
74
+ label('workspace', workspace),
75
+ label('model', model),
76
+ label('billing', billing),
77
+ label('can run', canRun),
78
+ '',
79
+ ];
80
+ /**
81
+ * ⚠️ ONLY WHEN A PROMPT ACTUALLY FOLLOWS. Printing "type what you want done"
82
+ * above a one-shot run that has already been given its task is an instruction
83
+ * for something the user cannot do, on the screen of a thing already working.
84
+ */
85
+ if (interactive) {
86
+ lines.push(' Type what you want done. /help for commands · exit to leave', '');
87
+ }
88
+ return lines.join('\n');
89
+ }
90
+
91
+ /**
92
+ * ⚠️ EXPORTED SO A TEST CAN ASSERT THE WIDTH RULE RATHER THAN TRUST IT. The
93
+ * banner is assembled from values supplied at runtime — a long model id or a
94
+ * deep workspace path is what would push it over, and neither is visible from
95
+ * reading this file.
96
+ */
97
+ export const MAX_BANNER_COLUMNS = 80;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acuvo-code",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Acuvo Code — the terminal client for the Acuvo capability registry. Zero dependencies, by design.",
5
5
  "type": "module",
6
6
  "bin": {