writethevision 7.0.2 → 7.0.4

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/package.json +1 -1
  2. package/src/cli.js +88 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "writethevision",
3
- "version": "7.0.2",
3
+ "version": "7.0.4",
4
4
  "description": "Write The Vision (WTV): vision-driven development with the Habakkuk workflow. 10 agents + 21 skills for Claude Code, Codex CLI, and OpenCode.",
5
5
  "author": "Christopher Hogg",
6
6
  "license": "MIT",
package/src/cli.js CHANGED
@@ -402,6 +402,73 @@ function getAgentLocations() {
402
402
  return locations;
403
403
  }
404
404
 
405
+ const BLOCK_FONT_3X5 = {
406
+ A: ['███', '█ █', '███', '█ █', '█ █'],
407
+ B: ['██ ', '█ █', '██ ', '█ █', '██ '],
408
+ C: ['███', '█ ', '█ ', '█ ', '███'],
409
+ D: ['██ ', '█ █', '█ █', '█ █', '██ '],
410
+ E: ['███', '█ ', '██ ', '█ ', '███'],
411
+ F: ['███', '█ ', '██ ', '█ ', '█ '],
412
+ G: ['███', '█ ', '█ █', '█ █', '███'],
413
+ H: ['█ █', '█ █', '███', '█ █', '█ █'],
414
+ I: ['███', ' █ ', ' █ ', ' █ ', '███'],
415
+ J: [' ██', ' █', ' █', '█ █', '██ '],
416
+ K: ['█ █', '█ █', '██ ', '█ █', '█ █'],
417
+ L: ['█ ', '█ ', '█ ', '█ ', '███'],
418
+ M: ['█ █', '███', '███', '█ █', '█ █'],
419
+ N: ['█ █', '███', '███', '███', '█ █'],
420
+ O: ['███', '█ █', '█ █', '█ █', '███'],
421
+ P: ['███', '█ █', '███', '█ ', '█ '],
422
+ Q: ['███', '█ █', '█ █', '███', ' █'],
423
+ R: ['███', '█ █', '███', '█ █', '█ █'],
424
+ S: ['███', '█ ', '███', ' █', '███'],
425
+ T: ['███', ' █ ', ' █ ', ' █ ', ' █ '],
426
+ U: ['█ █', '█ █', '█ █', '█ █', '███'],
427
+ V: ['█ █', '█ █', '█ █', '█ █', ' █ '],
428
+ W: ['█ █', '█ █', '███', '███', '█ █'],
429
+ X: ['█ █', '█ █', ' █ ', '█ █', '█ █'],
430
+ Y: ['█ █', '█ █', ' █ ', ' █ ', ' █ '],
431
+ Z: ['███', ' █', ' █ ', '█ ', '███'],
432
+ ' ': [' ', ' ', ' ', ' ', ' '],
433
+ '-': [' ', ' ', '███', ' ', ' '],
434
+ '?': ['███', ' █', ' ██', ' ', ' █ '],
435
+ };
436
+
437
+ function renderBlockText(text, { maxWidth = null, color = null, bold = false } = {}) {
438
+ const normalized = String(text || '').toUpperCase();
439
+ const glyphWidth = 3;
440
+ const letterGap = 1;
441
+ const maxCharsPerLine = maxWidth
442
+ ? Math.max(1, Math.floor((maxWidth + letterGap) / (glyphWidth + letterGap)))
443
+ : normalized.length;
444
+
445
+ const chunks = [];
446
+ for (let i = 0; i < normalized.length; i += maxCharsPerLine) {
447
+ chunks.push(normalized.slice(i, i + maxCharsPerLine));
448
+ }
449
+
450
+ const renderedLines = [];
451
+ for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
452
+ const chunk = chunks[chunkIndex];
453
+ for (let row = 0; row < 5; row++) {
454
+ const rowText = chunk
455
+ .split('')
456
+ .map(ch => (BLOCK_FONT_3X5[ch] ? BLOCK_FONT_3X5[ch][row] : BLOCK_FONT_3X5['?']?.[row] || '???'))
457
+ .join(' '.repeat(letterGap));
458
+
459
+ const prefix = color ? (bold ? color + c.bold : color) : '';
460
+ const suffix = color ? c.reset : '';
461
+ renderedLines.push(prefix + rowText + suffix);
462
+ }
463
+
464
+ if (chunkIndex !== chunks.length - 1) {
465
+ renderedLines.push('');
466
+ }
467
+ }
468
+
469
+ return renderedLines.join('\n');
470
+ }
471
+
405
472
  function parseAgentFile(filePath) {
406
473
  if (!existsSync(filePath)) return null;
407
474
 
@@ -1676,11 +1743,7 @@ async function meetTheTeam() {
1676
1743
  console.log(` ${c.bold}${c.yellow}PAUL — THE MASTERBUILDER${c.reset}`);
1677
1744
  console.log(` ${c.dim}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${c.reset}`);
1678
1745
  const paulAgent = parseAgentFile(join(TEMPLATES_DIR, 'agents', 'paul.md'));
1679
- if (paulAgent && paulAgent.asciiArt) {
1680
- console.log(paulAgent.asciiArt);
1681
- } else {
1682
- console.log(AVATARS.paul);
1683
- }
1746
+ console.log(AVATARS.paul || (paulAgent && paulAgent.asciiArt ? paulAgent.asciiArt : ''));
1684
1747
  await sleep(shortPause);
1685
1748
  console.log(`
1686
1749
  ${c.cyan}"According to the grace of God which is given unto me,${c.reset}
@@ -1710,11 +1773,7 @@ async function meetTheTeam() {
1710
1773
  console.log(` ${artisan.color}${c.bold}${artisan.name}${c.reset}`);
1711
1774
  const templatePath = join(TEMPLATES_DIR, 'agents', artisan.file);
1712
1775
  const agent = parseAgentFile(templatePath);
1713
- if (agent && agent.asciiArt) {
1714
- console.log(agent.asciiArt);
1715
- } else {
1716
- console.log(AVATARS[artisan.id]);
1717
- }
1776
+ console.log(AVATARS[artisan.id] || (agent && agent.asciiArt ? agent.asciiArt : ''));
1718
1777
  console.log(` ${c.dim}${artisan.domain}${c.reset}`);
1719
1778
  if (artisan.verse) {
1720
1779
  console.log(` ${c.dim}${artisan.verse.ref}${c.reset} ${c.dim}"${artisan.verse.text}"${c.reset}`);
@@ -3205,12 +3264,14 @@ async function dashboard() {
3205
3264
 
3206
3265
  // Header
3207
3266
  console.log(
3208
- ` ${c.magenta}
3209
- __ ___
3210
- \\ \\ / / |_ __
3211
- \\ \\/\\/ /| | \\/ /
3212
- \\_/\\_/ \\__|\\/
3213
- ${c.reset}`
3267
+ ` ${c.magenta}${c.bold}
3268
+ ██╗ ██╗████████╗██╗ ██╗
3269
+ ██║ ██║╚══██╔══╝██║ ██║
3270
+ ██║ █╗ ██║ ██║ ██║ ██║
3271
+ ██║███╗██║ ██║ ╚██╗ ██╔╝
3272
+ ╚███╔███╔╝ ██║ ╚████╔╝
3273
+ ╚══╝╚══╝ ╚═╝ ╚═══╝
3274
+ ${c.reset}`
3214
3275
  );
3215
3276
 
3216
3277
  console.log(` ${c.dim}v${getVersion()} • ${tool.toUpperCase()} MODE${c.reset}\n`);
@@ -3284,11 +3345,12 @@ function dashboardStatic() {
3284
3345
  // Banner
3285
3346
  console.log('');
3286
3347
  const wtvAscii = `
3287
- ${c.magenta}██ ██ ████████ ██ ██ ${c.reset}
3288
- ${c.magenta}██ ██ ██ ██ ██ ${c.reset}
3289
- ${c.magenta}██ █ ██ ██ ██ ██ ${c.reset}
3290
- ${c.magenta}██ ███ ██ ██ ██ ██ ${c.reset}
3291
- ${c.magenta} ███ ███ ██ ████ ${c.reset}`;
3348
+ ${c.magenta}${c.bold}██╗ ██╗████████╗██╗ ██╗${c.reset}
3349
+ ${c.magenta}${c.bold}██║ ██║╚══██╔══╝██║ ██║${c.reset}
3350
+ ${c.magenta}${c.bold}██║ █╗ ██║ ██║ ██║ ██║${c.reset}
3351
+ ${c.magenta}${c.bold}██║███╗██║ ██║ ╚██╗ ██╔╝${c.reset}
3352
+ ${c.magenta}${c.bold}╚███╔███╔╝ ██║ ╚████╔╝ ${c.reset}
3353
+ ${c.magenta}${c.bold} ╚══╝╚══╝ ╚═╝ ╚═══╝ ${c.reset}`;
3292
3354
 
3293
3355
  console.log(wtvAscii);
3294
3356
  console.log(drawBox([
@@ -3510,13 +3572,15 @@ async function agentsInteractive() {
3510
3572
  if (agent.wantsGlobal) statusText += c.blue + 'Global ' + c.reset;
3511
3573
  if (!agent.wantsLocal && !agent.wantsGlobal) statusText = c.dim + 'None' + c.reset;
3512
3574
 
3575
+ const terminalWidth = process.stdout.columns || 80;
3576
+ const detailWidth = Math.max(20, terminalWidth - detailStartX - 1);
3577
+ const nameBanner = renderBlockText(agent.name, { maxWidth: detailWidth, color: c.magenta, bold: true });
3578
+
3513
3579
  const details = [
3514
- `${c.magenta}${c.bold}${agent.name.toUpperCase()}${c.reset}`,
3580
+ nameBanner,
3515
3581
  `Status: ${statusText}`,
3516
3582
  '',
3517
3583
  `${c.dim}${agent.description}${c.reset}`,
3518
- '',
3519
- agent.asciiArt ? agent.asciiArt : `${c.dim}[ No Portrait ]${c.reset}`
3520
3584
  ];
3521
3585
 
3522
3586
  // Draw details