@mutmutco/hub 4.4.7 → 4.4.10

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 (2) hide show
  1. package/dist/index.cjs +24 -17
  2. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -28,6 +28,7 @@ __export(index_exports, {
28
28
  accent: () => accent,
29
29
  acquireSharedDocLock: () => acquireSharedDocLock,
30
30
  attentionRows: () => attentionRows,
31
+ autoupdateLine: () => autoupdateLine,
31
32
  brandLine: () => brandLine,
32
33
  buildWatcherCommand: () => buildWatcherCommand,
33
34
  checkAtomicity: () => checkAtomicity,
@@ -183,20 +184,26 @@ function wrapWords(text, width) {
183
184
  if (line) lines.push(line);
184
185
  return lines.length ? lines : [""];
185
186
  }
186
- function createFace({ product, color = false, columns }) {
187
+ function createFace({ product, color = false, columns, env = process.env }) {
187
188
  const identity = identityFor(product);
188
189
  const width = faceWidth(columns);
189
190
  const paint = (sgr, text) => color ? `\x1B[${sgr}m${text}\x1B[0m` : String(text);
190
191
  const bar = () => paint(PALETTE.muted, GLYPH.bar);
191
192
  const indent = " ".repeat(TITLE_COLUMN - 1);
192
- const welcome = () => [
193
+ const continuedPhases = new Set((env.MM_FACE_CONTINUES ?? "").split(",").map((phase) => phase.trim()).filter(Boolean));
194
+ const continuesFace = continuedPhases.size > 0;
195
+ const welcome = () => continuesFace ? [] : [
193
196
  `${paint(identity.accent, GLYPH.diamond)} ${paint(identity.accent, identity.name)} \u2014 Mutatis Mutandis`,
194
197
  bar(),
195
198
  `${bar()} ${identity.warm}`,
196
199
  bar()
197
200
  ];
201
+ const continues = (phase, kind = "ok") => {
202
+ const inherited = continuedPhases.delete(String(phase).trim());
203
+ return kind === "fail" ? false : inherited;
204
+ };
198
205
  const step = (title, seconds = null, kind = "ok") => {
199
- const glyph = kind === "fail" ? paint(identity.accent, GLYPH.cross) : kind === "note" ? paint(PALETTE.muted, GLYPH.hollow) : paint(PALETTE.green, GLYPH.check);
206
+ const glyph = kind === "fail" ? paint(identity.accent, GLYPH.cross) : kind === "note" ? paint(PALETTE.muted, GLYPH.dot) : paint(PALETTE.green, GLYPH.check);
200
207
  const time = seconds === null || seconds === void 0 ? "" : paint(PALETTE.muted, `${Math.max(0, Math.round(seconds))}s`);
201
208
  const column = Math.min(44, Math.max(0, width - 8));
202
209
  const reserved = time ? 6 : 0;
@@ -210,21 +217,21 @@ function createFace({ product, color = false, columns }) {
210
217
  const body = (Array.isArray(lines) ? lines : String(lines).split("\n")).flatMap((raw) => {
211
218
  const line = String(raw);
212
219
  if (visibleWidth(line) <= width - 6) return [line];
213
- const lead = /^\s*/u.exec(line)?.[0] ?? "";
214
- return wrapWords(line, width - 6 - lead.length).map((part) => `${lead}${part}`);
220
+ return wrapWords(line, width - 6);
215
221
  });
216
222
  const content = Math.min(width - 6, Math.max(...body.map(visibleWidth)));
217
223
  const rule = paint(identity.accent, GLYPH.rule.repeat(content + 4));
218
224
  const frame = (left, right) => `${paint(identity.accent, left)}${rule}${paint(identity.accent, right)}`;
225
+ const bodyRow = (line) => line.startsWith(GLYPH.check) ? `${paint(PALETTE.green, GLYPH.check)}${line.slice(1)}` : line;
219
226
  return [
220
227
  frame(GLYPH.boxTop, GLYPH.boxTopEnd),
221
- ...body.map((line) => `${paint(identity.accent, GLYPH.bar)} ${line}${" ".repeat(Math.max(0, content - visibleWidth(line)))} ${paint(identity.accent, GLYPH.bar)}`),
228
+ ...body.map((line) => `${paint(identity.accent, GLYPH.bar)} ${bodyRow(line)}${" ".repeat(Math.max(0, content - visibleWidth(line)))} ${paint(identity.accent, GLYPH.bar)}`),
222
229
  frame(GLYPH.boxBottom, GLYPH.boxBottomEnd)
223
230
  ];
224
231
  };
225
232
  const signOff = () => `${paint(identity.accent, GLYPH.diamond)} ${paint(identity.accent, `${identity.name} \xB7 Mutatis Mutandis`)}`;
226
233
  const refusal = (message3) => `${bar()} ${paint(identity.accent, GLYPH.cross)} ${message3}`;
227
- return { identity, width, welcome, step, relay, receipt, signOff, refusal, paint };
234
+ return { identity, width, welcome, continues, step, relay, receipt, signOff, refusal, paint };
228
235
  }
229
236
  var RELAY_INDENT = " ".repeat(TITLE_COLUMN - 1);
230
237
  var SEPARATOR = "\xB7";
@@ -251,8 +258,8 @@ function renderRows(face, rows) {
251
258
  const body = `${clip(subject, column).padEnd(column)} ${row.mark ? `${markGlyph(face, row.mark)} ` : ""}${tail2}`;
252
259
  lines.push(...face.relay(body).split("\n"));
253
260
  if (row.note) {
254
- for (const part of wrapWords(row.note, Math.max(16, face.width - column - 10))) {
255
- lines.push(...face.relay(`${" ".repeat(column)} ${part}`).split("\n"));
261
+ for (const part of wrapWords(row.note, Math.max(16, face.width - TITLE_COLUMN))) {
262
+ lines.push(...face.relay(part).split("\n"));
256
263
  }
257
264
  }
258
265
  }
@@ -276,7 +283,7 @@ function createSpinner(face, { animate, stream = process.stderr, intervalMs = 90
276
283
  };
277
284
  const draw = () => {
278
285
  if (!animate) return;
279
- const line = face.step(text, null, "note").split("\n")[0].replace(GLYPH.hollow, FRAMES[frame % FRAMES.length]);
286
+ const line = face.step(text, null, "note").split("\n")[0].replace(GLYPH.dot, FRAMES[frame % FRAMES.length]);
280
287
  stream.write(`\r\x1B[2K${line}`);
281
288
  frame += 1;
282
289
  };
@@ -3255,11 +3262,14 @@ function receiptText(summary, autoupdate, options = {}) {
3255
3262
  return [`${summary.exit >= 1 ? "\u2716" : "\u25CF"} mmi-hub is not ready \u2014 no green release yet (hourly retry)`, "", health];
3256
3263
  }
3257
3264
  const ready = counts.failed === 0;
3258
- const glyph = counts.failed > 0 ? "\u2716" : counts.retry > 0 ? "\u25CF" : dry ? "\u25C7" : "\u2714";
3265
+ const glyph = counts.failed > 0 ? "\u2716" : counts.retry > 0 ? "\u25CF" : dry ? "\u25CF" : "\u2714";
3259
3266
  const state = counts.failed > 0 ? `${counts.failed} of ${counts.total} surfaces failed` : counts.retry > 0 ? `${counts.retry} of ${counts.total} surfaces will retry` : counts.updated > 0 ? `${counts.updated}/${counts.total} surfaces ${dry ? "would update" : "updated"}` : `all ${counts.total} surfaces current`;
3260
3267
  const tail2 = autoupdate ? ` \xB7 ${autoupdate.ok ? "auto-update on" : `auto-update NOT enabled \u2014 ${autoupdate.detail}`}` : ` \xB7 ${summary.target}${dry ? " (planned)" : " (verified)"}`;
3261
3268
  return [`${glyph} mmi-hub is ${ready ? "ready" : "not ready"} \u2014 ${state}${tail2}`, "", health];
3262
3269
  }
3270
+ function autoupdateLine(state) {
3271
+ return state.ok ? 'Auto-update on \u2014 hourly task "MMI Fleet Updater".' : `Auto-update NOT enabled \u2014 ${state.detail}`;
3272
+ }
3263
3273
  function attentionRows(summary) {
3264
3274
  return collectRows(summary).filter((row) => row.kind === "failed" || row.kind === "retry" || row.kind === "pending").map((row) => ({
3265
3275
  surface: row.name,
@@ -3668,9 +3678,7 @@ async function main(args = process.argv.slice(2)) {
3668
3678
  const handedOff = handOff(summary.reexec, ["update", ...args.filter((arg) => arg !== "install" && arg !== "--shipped" && arg !== shippedTarget)]);
3669
3679
  const scheduled = installTask();
3670
3680
  if (!json) {
3671
- process.stdout.write(scheduled.ok ? ` Auto-update on \u2014 hourly task "MMI Fleet Updater".
3672
- ` : ` Auto-update NOT enabled \u2014 ${scheduled.detail}
3673
- `);
3681
+ process.stdout.write(autoupdateLine(scheduled) + "\n");
3674
3682
  } else {
3675
3683
  process.stdout.write(JSON.stringify({ convergence: summary, autoupdate: scheduled }, null, 2) + "\n");
3676
3684
  }
@@ -3683,9 +3691,7 @@ async function main(args = process.argv.slice(2)) {
3683
3691
  finishFace(face, summary, schedule, dryRun);
3684
3692
  } else {
3685
3693
  if (!rendered) printReconcile(summary, false, dryRun);
3686
- process.stdout.write(schedule.ok ? ` Auto-update on \u2014 hourly task "MMI Fleet Updater".
3687
- ` : ` Auto-update NOT enabled \u2014 ${schedule.detail}
3688
- `);
3694
+ process.stdout.write(autoupdateLine(schedule) + "\n");
3689
3695
  }
3690
3696
  return Math.max(summary.exit, schedule.ok ? 0 : 1);
3691
3697
  }
@@ -3720,6 +3726,7 @@ if (typeof require !== "undefined" && require.main === module) {
3720
3726
  accent,
3721
3727
  acquireSharedDocLock,
3722
3728
  attentionRows,
3729
+ autoupdateLine,
3723
3730
  brandLine,
3724
3731
  buildWatcherCommand,
3725
3732
  checkAtomicity,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/hub",
3
- "version": "4.4.7",
3
+ "version": "4.4.10",
4
4
  "description": "Install and maintain the MMI CLI and every present host surface from one release-gated Hub command.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -26,7 +26,7 @@
26
26
  "typecheck": "tsc --noEmit"
27
27
  },
28
28
  "dependencies": {
29
- "@mutmutco/installer-face": "^0.2.0"
29
+ "@mutmutco/installer-face": "^0.2.3"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.0.0",