spectoflow 0.16.2 → 0.16.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.
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ /*
4
+ * Printed after `npm install -g spectoflow`: the brand welcome + first steps.
5
+ * Guarded to a GLOBAL, interactive (TTY) install so it never spams CI, dependency installs, or logs,
6
+ * and wrapped so a banner can never fail an install. Note: npm may buffer lifecycle-script output —
7
+ * if it doesn't appear, `spectoflow` (no args) and `spectoflow init` show the same brand.
8
+ */
9
+ try {
10
+ if (process.env.npm_config_global === 'true' && process.stdout.isTTY) {
11
+ const brand = require('../lib/brand');
12
+ const version = require('../package.json').version;
13
+ const useColor = !process.env.NO_COLOR;
14
+ const paint = (code) => (s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : String(s));
15
+ const c = { white: paint('97'), amber: paint('38;5;179'), dim: paint('2'), bold: paint('1'), g: paint('32') };
16
+ process.stdout.write(brand.logo(c, version));
17
+ process.stdout.write(`\n ${c.bold('Get started')}\n`);
18
+ process.stdout.write(` ${c.g('spectoflow init')} scaffold a project in the current folder\n`);
19
+ process.stdout.write(` ${c.g('spectoflow --help')} all commands\n\n`);
20
+ }
21
+ } catch { /* never break an install over a welcome banner */ }
package/bin/spectoflow.js CHANGED
@@ -20,46 +20,14 @@ const cmd = argv[0] || 'help';
20
20
  // Tiny ANSI colouriser — no dependency; disabled when not a TTY or NO_COLOR is set.
21
21
  const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
22
22
  const paint = (code) => (s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : String(s));
23
- const c = { g: paint('32'), cy: paint('36'), b: paint('34'), y: paint('33'), dim: paint('2'), bold: paint('1'), amber: paint('38;5;179') };
23
+ const c = { g: paint('32'), cy: paint('36'), b: paint('34'), y: paint('33'), dim: paint('2'), bold: paint('1'), amber: paint('38;5;179'), white: paint('97') };
24
24
 
25
25
  // ---- branding ---------------------------------------------------------------
26
- // The spectoflow mark in ASCII: a flat-top hexagon around the angular "S" (flow), rasterized to fit
27
- // a terminal. Shown at the reading moments (init / help / list); secondary outputs use brandLine().
28
- const LOGO = [
29
- ' ########',
30
- ' ###### #######',
31
- ' ####### ######',
32
- ' ###### ######',
33
- ' ###### #### ######',
34
- ' ##### ###### ####',
35
- ' ### ###### ####',
36
- ' ### ##### ####',
37
- ' ### #### ## ####',
38
- ' ### #### ######### ####',
39
- ' ### #### ####### ##### ####',
40
- ' ### ######## ### ####',
41
- ' ### ## ### ####',
42
- ' ### #### ####',
43
- ' ### ###### ####',
44
- ' ### ###### ####',
45
- ' #### ###### ####',
46
- ' ###### ### ######',
47
- ' ###### ######',
48
- ' ###### ######',
49
- ' ###### ######',
50
- ' ##########',
51
- ' ####',
52
- ];
53
- const LOGO_W = 41; // widest logo line, for centering the wordmark under it
54
- const NAME = 's p e c t o f l o w';
55
- const TAGLINE = 'agent-agnostic spec-driven development · real-time control plane';
56
- // Full logo block — hexagon mark + centered wordmark + version. For init, help and list.
57
- function logo() {
58
- const art = LOGO.map((l) => ' ' + c.amber(l)).join('\n');
59
- const pad = ' '.repeat(Math.max(0, Math.round((2 + LOGO_W - NAME.length) / 2)));
60
- return `\n${art}\n\n${pad}${c.bold(c.amber(NAME))}\n ${c.dim('v' + VERSION + ' · ' + TAGLINE)}\n`;
61
- }
62
- // One-line brand — for the header of secondary command outputs.
26
+ // Shared ASCII brand (white hexagon + amber wordmark) lives in lib/brand.js so the CLI and the
27
+ // postinstall welcome render the exact same art.
28
+ const brand = require('../lib/brand');
29
+ const logo = () => brand.logo(c, VERSION); // white hexagon + centered amber wordmark (init/update)
30
+ const wordmark = () => brand.wordmark(c, VERSION); // amber wordmark alone (help + explore)
63
31
  const brandLine = () => `${c.amber('spectoflow')} ${c.dim('v' + VERSION)}`;
64
32
 
65
33
  // ---- framework introspection (list agents / skills / workflow) --------------
@@ -266,7 +234,7 @@ function update() {
266
234
  const detail = note ? c.dim(note) : c.dim(list.slice(0, 6).join(', ') + (list.length > 6 ? ` +${list.length - 6} more` : ''));
267
235
  console.log(` ${sym} ${painter(label.padEnd(9))} ${n} ${detail}`);
268
236
  };
269
- console.log('');
237
+ console.log(logo());
270
238
  console.log(` ${c.bold('spectoflow update')} ${c.dim(from)} ${c.amber('→')} ${c.bold(r.toVersion)}${dryRun ? c.dim(' (dry-run)') : ''}`);
271
239
  console.log('');
272
240
  row(c.g('✓'), 'refreshed', r.refreshed, c.g);
@@ -403,7 +371,7 @@ function printWorkflow(withBrand = true) {
403
371
  }
404
372
  function listAll() {
405
373
  const { scope } = frameworkSource();
406
- console.log(logo());
374
+ console.log(wordmark());
407
375
  console.log(`${c.bold('Agents')} ${c.dim('— stable team personas (' + scope + ')')}`);
408
376
  printAgents(false);
409
377
  console.log(`\n${c.bold('Skills')} ${c.dim('— evolving procedures')}`);
@@ -414,7 +382,7 @@ function listAll() {
414
382
  }
415
383
 
416
384
  // ---- help (global + per-command) --------------------------------------------
417
- const help = () => console.log(`${logo()}
385
+ const help = () => console.log(`${wordmark()}
418
386
  ${c.dim('Usage:')} spectoflow ${c.g('<command>')} ${c.dim('[options]')} ${c.dim('· append -h to any command for its help')}
419
387
 
420
388
  ${c.bold('Project')}
@@ -473,7 +441,12 @@ const HELP = {
473
441
  const showHelp = (name) => console.log('\n' + HELP[name].trim() + '\n');
474
442
 
475
443
  // ---- dispatch ---------------------------------------------------------------
476
- const fns = { init, update, dashboard, stop: stopDashboard, status, list: listAll, agents: () => printAgents(), skills: () => printSkills(), workflow: () => printWorkflow(), help, version };
444
+ const fns = {
445
+ init, update, dashboard, stop: stopDashboard, status, list: listAll, help, version,
446
+ agents: () => { console.log(wordmark()); printAgents(false); },
447
+ skills: () => { console.log(wordmark()); printSkills(false); },
448
+ workflow: () => { console.log(wordmark()); printWorkflow(false); },
449
+ };
477
450
  const wantsHelp = argv.slice(1).some((a) => a === '-h' || a === '--help');
478
451
 
479
452
  if (['-v', '-V', '--version', 'version'].includes(cmd)) version();
package/lib/brand.js ADDED
@@ -0,0 +1,64 @@
1
+ 'use strict';
2
+ /*
3
+ * Shared spectoflow ASCII brand — used by the CLI (bin/spectoflow.js) and the postinstall welcome
4
+ * (bin/postinstall.js). The hexagon mark is drawn WHITE; the compact figlet wordmark is drawn AMBER
5
+ * and centred under the mark. Callers pass their own colouriser `c` (with .white/.amber/.dim) and the
6
+ * version string, so this stays presentation-agnostic and zero-dependency.
7
+ */
8
+ const LOGO = [
9
+ ' ########',
10
+ ' ###### #######',
11
+ ' ####### ######',
12
+ ' ###### ######',
13
+ ' ###### #### ######',
14
+ ' ##### ###### ####',
15
+ ' #### ###### ####',
16
+ ' #### ##### ####',
17
+ ' #### #### ## ####',
18
+ ' #### #### ######### ####',
19
+ ' #### #### ####### ##### ####',
20
+ ' #### ######## ### ####',
21
+ ' #### ## ### ####',
22
+ ' #### #### ####',
23
+ ' #### ###### ####',
24
+ ' #### ###### ####',
25
+ ' #### ###### ####',
26
+ ' ###### ### ######',
27
+ ' ###### ######',
28
+ ' ###### ######',
29
+ ' ###### ######',
30
+ ' ##########',
31
+ ' ####',
32
+ ];
33
+ const NAME = [
34
+ ' _ __ _',
35
+ ' ____ __ ___ __| |_ ___ / _| |_____ __ __',
36
+ " (_-< '_ \\/ -_) _| _/ _ \\ _| / _ \\ V V /",
37
+ ' /__/ .__/\\___\\__|\\__\\___/_| |_\\___/\\_/\\_/',
38
+ ' |_|',
39
+ ];
40
+ const NAME_W = Math.max(...NAME.map((l) => l.length));
41
+ const TAGLINE = 'agent-agnostic spec-driven development · real-time control plane';
42
+ const INDENT = ' ';
43
+
44
+ // Amber wordmark; when `centerUnder`, centred beneath the hexagon's true horizontal midpoint.
45
+ function nameBlock(c, centerUnder) {
46
+ let pad = INDENT;
47
+ if (centerUnder) {
48
+ let lo = Infinity, hi = 0;
49
+ for (const l of LOGO) { const i = l.search(/#/); if (i >= 0) { lo = Math.min(lo, i); hi = Math.max(hi, l.length - 1); } }
50
+ pad = ' '.repeat(Math.max(0, Math.round(INDENT.length + (lo + hi) / 2 - NAME_W / 2)));
51
+ }
52
+ return NAME.map((l) => pad + c.amber(l)).join('\n');
53
+ }
54
+ // White hexagon + centred amber wordmark + version. For init, update and the install welcome.
55
+ function logo(c, version) {
56
+ const art = LOGO.map((l) => INDENT + c.white(l)).join('\n');
57
+ return `\n${art}\n\n${nameBlock(c, true)}\n\n${INDENT}${c.dim('v' + version + ' · ' + TAGLINE)}\n`;
58
+ }
59
+ // Just the amber wordmark + version. For help and the explore commands.
60
+ function wordmark(c, version) {
61
+ return `\n${nameBlock(c, false)}\n\n${INDENT}${c.dim('v' + version + ' · ' + TAGLINE)}\n`;
62
+ }
63
+
64
+ module.exports = { LOGO, NAME, TAGLINE, logo, wordmark };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spectoflow",
3
- "version": "0.16.2",
3
+ "version": "0.16.4",
4
4
  "description": "Agent-agnostic spec-driven development framework + real-time local control plane. Markdown artifacts, intent router, workflow-by-scope.",
5
5
  "keywords": [
6
6
  "spec-driven-development",
@@ -40,6 +40,7 @@
40
40
  ],
41
41
  "scripts": {
42
42
  "status": "node bin/spectoflow.js status",
43
+ "postinstall": "node bin/postinstall.js",
43
44
  "test": "node --test"
44
45
  },
45
46
  "engines": {