@entelligentsia/forgecli 0.8.4 → 0.9.1
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/CHANGELOG.md +61 -0
- package/README.md +165 -2
- package/dist/bin/argv.d.ts +2 -2
- package/dist/bin/argv.js +17 -0
- package/dist/bin/argv.js.map +1 -1
- package/dist/bin/config.d.ts +69 -0
- package/dist/bin/config.js +315 -0
- package/dist/bin/config.js.map +1 -0
- package/dist/bin/doctor.d.ts +1 -0
- package/dist/bin/doctor.js +12 -0
- package/dist/bin/doctor.js.map +1 -1
- package/dist/bin/forge.js +7 -0
- package/dist/bin/forge.js.map +1 -1
- package/dist/extensions/forgecli/config-command.d.ts +8 -0
- package/dist/extensions/forgecli/config-command.js +66 -0
- package/dist/extensions/forgecli/config-command.js.map +1 -0
- package/dist/extensions/forgecli/config-layer.d.ts +38 -0
- package/dist/extensions/forgecli/config-layer.js +68 -0
- package/dist/extensions/forgecli/config-layer.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/component.d.ts +35 -0
- package/dist/extensions/forgecli/config-tui/component.js +236 -0
- package/dist/extensions/forgecli/config-tui/component.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/handler.d.ts +40 -0
- package/dist/extensions/forgecli/config-tui/handler.js +240 -0
- package/dist/extensions/forgecli/config-tui/handler.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/index.d.ts +5 -0
- package/dist/extensions/forgecli/config-tui/index.js +5 -0
- package/dist/extensions/forgecli/config-tui/index.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/keys.d.ts +26 -0
- package/dist/extensions/forgecli/config-tui/keys.js +33 -0
- package/dist/extensions/forgecli/config-tui/keys.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/plugin-config-reader.d.ts +23 -0
- package/dist/extensions/forgecli/config-tui/plugin-config-reader.js +58 -0
- package/dist/extensions/forgecli/config-tui/plugin-config-reader.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/advanced-menu.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js +83 -0
- package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/confirm-quit.d.ts +11 -0
- package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js +54 -0
- package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/override-editor.d.ts +11 -0
- package/dist/extensions/forgecli/config-tui/screens/override-editor.js +233 -0
- package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +91 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list.js +71 -0
- package/dist/extensions/forgecli/config-tui/screens/overrides-list.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-editor.d.ts +10 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-editor.js +182 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-editor.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-picker.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-picker.js +76 -0
- package/dist/extensions/forgecli/config-tui/screens/persona-picker.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/personas-list.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/personas-list.js +98 -0
- package/dist/extensions/forgecli/config-tui/screens/personas-list.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/shared.d.ts +29 -0
- package/dist/extensions/forgecli/config-tui/screens/shared.js +100 -0
- package/dist/extensions/forgecli/config-tui/screens/shared.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/show-resolved.d.ts +23 -0
- package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +128 -0
- package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-menu.d.ts +7 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-menu.js +135 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-menu.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-picker.d.ts +9 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-picker.js +122 -0
- package/dist/extensions/forgecli/config-tui/screens/tier-picker.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens/types.d.ts +24 -0
- package/dist/extensions/forgecli/config-tui/screens/types.js +5 -0
- package/dist/extensions/forgecli/config-tui/screens/types.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/screens.d.ts +24 -0
- package/dist/extensions/forgecli/config-tui/screens.js +78 -0
- package/dist/extensions/forgecli/config-tui/screens.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +11 -0
- package/dist/extensions/forgecli/config-tui/state/buffer.js +91 -0
- package/dist/extensions/forgecli/config-tui/state/buffer.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/constants.d.ts +4 -0
- package/dist/extensions/forgecli/config-tui/state/constants.js +14 -0
- package/dist/extensions/forgecli/config-tui/state/constants.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/index.d.ts +6 -0
- package/dist/extensions/forgecli/config-tui/state/index.js +9 -0
- package/dist/extensions/forgecli/config-tui/state/index.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/init.d.ts +2 -0
- package/dist/extensions/forgecli/config-tui/state/init.js +30 -0
- package/dist/extensions/forgecli/config-tui/state/init.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/model.d.ts +192 -0
- package/dist/extensions/forgecli/config-tui/state/model.js +4 -0
- package/dist/extensions/forgecli/config-tui/state/model.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/reducer.d.ts +2 -0
- package/dist/extensions/forgecli/config-tui/state/reducer.js +212 -0
- package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +91 -0
- package/dist/extensions/forgecli/config-tui/state/selectors.js +231 -0
- package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/state.d.ts +6 -0
- package/dist/extensions/forgecli/config-tui/state.js +11 -0
- package/dist/extensions/forgecli/config-tui/state.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/theme.d.ts +37 -0
- package/dist/extensions/forgecli/config-tui/theme.js +88 -0
- package/dist/extensions/forgecli/config-tui/theme.js.map +1 -0
- package/dist/extensions/forgecli/config-tui/tier-meta.d.ts +28 -0
- package/dist/extensions/forgecli/config-tui/tier-meta.js +69 -0
- package/dist/extensions/forgecli/config-tui/tier-meta.js.map +1 -0
- package/dist/extensions/forgecli/config-writer.d.ts +16 -0
- package/dist/extensions/forgecli/config-writer.js +63 -0
- package/dist/extensions/forgecli/config-writer.js.map +1 -0
- package/dist/extensions/forgecli/fix-bug.js +85 -1
- package/dist/extensions/forgecli/fix-bug.js.map +1 -1
- package/dist/extensions/forgecli/forge-cli-schema.json +54 -0
- package/dist/extensions/forgecli/forge-commands.js +3 -8
- package/dist/extensions/forgecli/forge-commands.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.d.ts +13 -0
- package/dist/extensions/forgecli/forge-subagent.js +19 -0
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/index.js +16 -0
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/input-router.d.ts +33 -0
- package/dist/extensions/forgecli/input-router.js +133 -0
- package/dist/extensions/forgecli/input-router.js.map +1 -0
- package/dist/extensions/forgecli/model-resolver.d.ts +32 -0
- package/dist/extensions/forgecli/model-resolver.js +65 -0
- package/dist/extensions/forgecli/model-resolver.js.map +1 -0
- package/dist/extensions/forgecli/model-validator.d.ts +29 -0
- package/dist/extensions/forgecli/model-validator.js +107 -0
- package/dist/extensions/forgecli/model-validator.js.map +1 -0
- package/dist/extensions/forgecli/run-sprint.js +59 -0
- package/dist/extensions/forgecli/run-sprint.js.map +1 -1
- package/dist/extensions/forgecli/run-task.js +93 -1
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/thread-switcher.js +5 -2
- package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
- package/dist/extensions/forgecli/whats-new-widget.js +5 -2
- package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
- package/package.json +11 -3
- package/dist/extensions/forgecli/review-command.d.ts +0 -2
- package/dist/extensions/forgecli/review-command.js +0 -184
- package/dist/extensions/forgecli/review-command.js.map +0 -1
- package/dist/forge-payload/.tools/banners.cjs +0 -435
- package/dist/forge-payload/.tools/build-context-pack.cjs +0 -290
- package/dist/forge-payload/.tools/build-init-context.cjs +0 -322
- package/dist/forge-payload/.tools/build-overlay.cjs +0 -326
- package/dist/forge-payload/.tools/build-persona-pack.cjs +0 -226
- package/dist/forge-payload/.tools/collate.cjs +0 -1041
- package/dist/forge-payload/.tools/generation-manifest.cjs +0 -311
- package/dist/forge-payload/.tools/lib/forge-root.cjs +0 -59
- package/dist/forge-payload/.tools/lib/paths.cjs +0 -29
- package/dist/forge-payload/.tools/lib/pricing.cjs +0 -165
- package/dist/forge-payload/.tools/lib/project-root.cjs +0 -32
- package/dist/forge-payload/.tools/lib/result.js +0 -40
- package/dist/forge-payload/.tools/lib/store-facade.cjs +0 -162
- package/dist/forge-payload/.tools/lib/store-nlp.cjs +0 -250
- package/dist/forge-payload/.tools/lib/store-query-exec.cjs +0 -272
- package/dist/forge-payload/.tools/lib/validate.js +0 -141
- package/dist/forge-payload/.tools/manage-config.cjs +0 -340
- package/dist/forge-payload/.tools/manage-versions.cjs +0 -365
- package/dist/forge-payload/.tools/package.json +0 -3
- package/dist/forge-payload/.tools/parse-gates.cjs +0 -151
- package/dist/forge-payload/.tools/parse-verdict.cjs +0 -67
- package/dist/forge-payload/.tools/preflight-gate.cjs +0 -350
- package/dist/forge-payload/.tools/prompts/sprint-plan-prompt.md +0 -70
- package/dist/forge-payload/.tools/schemas/task-list.schema.json +0 -53
- package/dist/forge-payload/.tools/seed-store.cjs +0 -237
- package/dist/forge-payload/.tools/store-cli.cjs +0 -1226
- package/dist/forge-payload/.tools/store-query.cjs +0 -319
- package/dist/forge-payload/.tools/store.cjs +0 -315
- package/dist/forge-payload/.tools/substitute-placeholders.cjs +0 -625
- package/dist/forge-payload/.tools/validate-store.cjs +0 -593
|
@@ -1,435 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// Forge Banner Library
|
|
4
|
-
// Reusable agent identity display for tools, hooks, and skills.
|
|
5
|
-
//
|
|
6
|
-
// Render modes:
|
|
7
|
-
// render(name) — full ASCII art block + emoji + name + tagline
|
|
8
|
-
// badge(name) — single line: emoji + bold name + dim tagline
|
|
9
|
-
// mark(name) — emoji only (for use alongside 〇△× status marks)
|
|
10
|
-
// progressBar(n,total,opt) — unicode block bar with optional gradient + label
|
|
11
|
-
// subtitle(text, opts) — dim italic line for under-banner taglines
|
|
12
|
-
// phaseHeader(...) — convenience: badge + em-dash banner + progress bar
|
|
13
|
-
//
|
|
14
|
-
// Plain mode: ANSI escapes are stripped when any of these is true:
|
|
15
|
-
// - env FORGE_BANNERS_PLAIN is set to a non-empty value
|
|
16
|
-
// - env NO_COLOR is set to a non-empty value
|
|
17
|
-
// - process.stdout.isTTY === false
|
|
18
|
-
// - CLI flag --plain is passed
|
|
19
|
-
//
|
|
20
|
-
// Usage (module):
|
|
21
|
-
// const banners = require('./banners.cjs');
|
|
22
|
-
// console.log(banners.render('forge'));
|
|
23
|
-
// console.log(banners.progressBar(5, 12, { label: 'Templates', color: [255,208,122] }));
|
|
24
|
-
//
|
|
25
|
-
// Usage (CLI):
|
|
26
|
-
// node banners.cjs forge
|
|
27
|
-
// node banners.cjs --badge north
|
|
28
|
-
// node banners.cjs --mark tide
|
|
29
|
-
// node banners.cjs --gallery
|
|
30
|
-
// node banners.cjs --list
|
|
31
|
-
// node banners.cjs --plain forge
|
|
32
|
-
// node banners.cjs --subtitle "Forging your SDLC"
|
|
33
|
-
// node banners.cjs --progress 5 12 "Templates"
|
|
34
|
-
// node banners.cjs --phase 7 12 "Workflows" ember fast
|
|
35
|
-
|
|
36
|
-
// ─── Plain-mode detection ─────────────────────────────────────────────────────
|
|
37
|
-
// Resolved at call-time so tests can flip env vars dynamically.
|
|
38
|
-
function isPlain() {
|
|
39
|
-
if (process.env.FORGE_BANNERS_PLAIN) return true;
|
|
40
|
-
if (process.env.NO_COLOR) return true;
|
|
41
|
-
if (process.stdout && process.stdout.isTTY === false) return true;
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Strip ANSI escape sequences (CSI). Conservative — matches \x1b[...m and friends.
|
|
46
|
-
const ANSI_RE = /\x1b\[[0-9;]*[A-Za-z]/g;
|
|
47
|
-
function stripAnsi(s) {
|
|
48
|
-
return String(s).replace(ANSI_RE, '');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Soft override — set by `--plain` CLI flag to force plain mode for one run.
|
|
52
|
-
let FORCE_PLAIN = false;
|
|
53
|
-
|
|
54
|
-
// ─── ANSI helpers ─────────────────────────────────────────────────────────────
|
|
55
|
-
const R = '\x1b[0m';
|
|
56
|
-
const B = '\x1b[1m';
|
|
57
|
-
const D = '\x1b[2m';
|
|
58
|
-
const I = '\x1b[3m';
|
|
59
|
-
const f = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
60
|
-
|
|
61
|
-
// ─── Mode tints ───────────────────────────────────────────────────────────────
|
|
62
|
-
// Mode-aware accent colour for progress bars and subtitles. Used by phaseHeader.
|
|
63
|
-
const MODE_TINTS = {
|
|
64
|
-
fast: [255, 208, 122], // lantern yellow
|
|
65
|
-
full: [255, 138, 60], // ember orange
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// ─── Zen blue ─────────────────────────────────────────────────────────────────
|
|
69
|
-
// System-wide horizontal-rule tint. Applied to em-dash separators in
|
|
70
|
-
// phaseHeader, ruleLine, and ensure-ready.cjs --announce framing. Picked to
|
|
71
|
-
// read calm and cool without competing with banner colours.
|
|
72
|
-
const ZEN_BLUE = [100, 140, 200];
|
|
73
|
-
|
|
74
|
-
// ─── Banner registry ───────────────────────────────────────────────────────────
|
|
75
|
-
const BANNERS = {
|
|
76
|
-
|
|
77
|
-
ember: {
|
|
78
|
-
emoji: '🔥',
|
|
79
|
-
tagline: 'heat · ignition · drive',
|
|
80
|
-
name: 'EMBER',
|
|
81
|
-
kanji: '炎',
|
|
82
|
-
color: [255, 170, 60],
|
|
83
|
-
art: ` ${f(255,240,100)}) ${f(255,200,50)}) ${f(255,140,20)}(${f(230,80,10)}🔥${f(255,140,20)}) ${f(230,80,10)}~∿~ ${f(170,30,5)}≋≋≋`,
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
tide: {
|
|
87
|
-
emoji: '🌊',
|
|
88
|
-
tagline: 'rhythm · pull · depth',
|
|
89
|
-
name: 'TIDE',
|
|
90
|
-
kanji: '潮',
|
|
91
|
-
color: [110, 200, 255],
|
|
92
|
-
art: ` ${f(210,240,255)}∿ ${f(130,200,245)}≋≋≋ ${f(60,140,210)}≋≋≋ ${f(25,85,175)}▓▓▓ ${f(10,45,130)}▓▓▓`,
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
oracle: {
|
|
96
|
-
emoji: '🌕',
|
|
97
|
-
tagline: 'sight · pattern · knowing',
|
|
98
|
-
name: 'ORACLE',
|
|
99
|
-
kanji: '神託',
|
|
100
|
-
color: [210, 160, 255],
|
|
101
|
-
art: ` ${f(160,80,240)}· ◌ ${f(190,110,255)}◎ ${f(255,220,100)}◉ ${f(190,110,255)}◎ ${f(160,80,240)}◌ ·`,
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
rift: {
|
|
105
|
-
emoji: '⚡',
|
|
106
|
-
tagline: 'edge · fracture · crossing',
|
|
107
|
-
name: 'RIFT',
|
|
108
|
-
kanji: '裂',
|
|
109
|
-
color: [100, 255, 240],
|
|
110
|
-
art: ` ${f(0,240,230)}▓▒░ ${f(180,0,220)}╲ ${f(0,255,240)}⚡${f(180,0,220)} ╱ ${f(0,240,230)}░▒▓`,
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
bloom: {
|
|
114
|
-
emoji: '🌸',
|
|
115
|
-
tagline: 'growth · opening · becoming',
|
|
116
|
-
name: 'BLOOM',
|
|
117
|
-
kanji: '開花',
|
|
118
|
-
color: [255, 160, 190],
|
|
119
|
-
art: ` ${f(255,160,200)}✿ ✿ ${f(255,120,170)}✾ ${f(255,220,100)}✽ ${f(255,120,170)}✾ ${f(255,160,200)}✿ ✿`,
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
north: {
|
|
123
|
-
emoji: '🧭',
|
|
124
|
-
tagline: 'direction · clarity · cold',
|
|
125
|
-
name: 'NORTH',
|
|
126
|
-
kanji: '北',
|
|
127
|
-
color: [190, 225, 255],
|
|
128
|
-
art: ` ${f(200,230,255)}✦ ${f(150,195,240)}╱ ${f(100,160,230)}◈ ${f(150,195,240)}╲ ${f(200,230,255)}✦`,
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
lumen: {
|
|
132
|
-
emoji: '✨',
|
|
133
|
-
tagline: 'light · warmth · clarity',
|
|
134
|
-
name: 'LUMEN',
|
|
135
|
-
kanji: '光',
|
|
136
|
-
color: [255, 245, 150],
|
|
137
|
-
art: ` ${f(255,255,200)}✧ ${f(255,245,160)}── ${f(255,255,255)}◉ ${f(255,245,160)}── ${f(255,255,200)}✧`,
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
forge: {
|
|
141
|
-
emoji: '🔨',
|
|
142
|
-
tagline: 'making · heat · craft',
|
|
143
|
-
name: 'FORGE',
|
|
144
|
-
kanji: '鍛冶',
|
|
145
|
-
color: [255, 160, 40],
|
|
146
|
-
art: ` ${f(255,230,80)}✦ ${f(200,80,20)}▄${f(230,100,30)}▓▓▓▓▓${f(200,80,20)}▄ ${f(255,160,40)}≋ ≋ ≋`,
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
drift: {
|
|
150
|
-
emoji: '🍃',
|
|
151
|
-
tagline: 'ease · letting go · flow',
|
|
152
|
-
name: 'DRIFT',
|
|
153
|
-
kanji: '漂流',
|
|
154
|
-
color: [150, 200, 165],
|
|
155
|
-
art: ` ${f(160,200,170)}· ${f(140,180,155)}· ${f(120,165,140)}· ${f(100,150,125)}· ${f(80,135,110)}·`,
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
void: {
|
|
159
|
-
emoji: '🌑',
|
|
160
|
-
tagline: 'depth · silence · potential',
|
|
161
|
-
name: 'VOID',
|
|
162
|
-
kanji: '虚空',
|
|
163
|
-
color: [130, 100, 200],
|
|
164
|
-
art: ` ${f(30,20,60)} · ${f(70,50,120)}◌ ${f(50,35,90)}· `,
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
entelligentsia: {
|
|
168
|
-
emoji: '🔗',
|
|
169
|
-
tagline: 'linked · intellect · becoming',
|
|
170
|
-
name: 'ENTELLIGENTSIA',
|
|
171
|
-
kanji: '知性',
|
|
172
|
-
color: [140, 200, 60],
|
|
173
|
-
art: ` ${f(110,110,115)}╭──╯ ${f(140,200,60)}─╮ ╭─ ${f(110,110,115)}╰──╮`,
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
// ─── Render helpers ────────────────────────────────────────────────────────────
|
|
179
|
-
|
|
180
|
-
/** Dim dot rule — use between banners in a gallery */
|
|
181
|
-
function rule() {
|
|
182
|
-
return ` ${f(45,45,65)}${'·'.repeat(32)}${R}`;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Full banner: ASCII art block + emoji + name + tagline.
|
|
187
|
-
* @param {string} name Banner key (case-insensitive).
|
|
188
|
-
* @returns {string}
|
|
189
|
-
*/
|
|
190
|
-
function render(name) {
|
|
191
|
-
const b = _get(name);
|
|
192
|
-
const [r, g, bl] = b.color;
|
|
193
|
-
const kanji = b.kanji ? ` ${D}${f(r,g,bl)}${b.kanji}${R}` : '';
|
|
194
|
-
const label = ` ${b.emoji} ${B}${f(r,g,bl)}${b.name}${R}${kanji} ${D}${f(r,g,bl)}${b.tagline}${R}`;
|
|
195
|
-
const out = '\n' + b.art + R + '\n' + label + '\n';
|
|
196
|
-
return _maybePlain(out);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Badge: single line — emoji + bold name + dim tagline.
|
|
201
|
-
* Fits inline in status output or skill headers.
|
|
202
|
-
* @param {string} name
|
|
203
|
-
* @returns {string}
|
|
204
|
-
*/
|
|
205
|
-
function badge(name) {
|
|
206
|
-
const b = _get(name);
|
|
207
|
-
const [r, g, bl] = b.color;
|
|
208
|
-
const kanji = b.kanji ? ` ${D}${f(r,g,bl)}${b.kanji}${R}` : '';
|
|
209
|
-
return _maybePlain(`${b.emoji} ${B}${f(r,g,bl)}${b.name}${R}${kanji} ${D}${f(r,g,bl)}${b.tagline}${R}`);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Mark: emoji only.
|
|
214
|
-
* Use alongside 〇△× status marks for agent attribution.
|
|
215
|
-
* @param {string} name
|
|
216
|
-
* @returns {string}
|
|
217
|
-
*/
|
|
218
|
-
function mark(name) {
|
|
219
|
-
return _get(name).emoji;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Progress bar: unicode block bar with optional gradient tint and label.
|
|
224
|
-
* ▰▰▰▰▰▱▱▱▱▱▱▱ Phase 5/12 · Templates
|
|
225
|
-
*
|
|
226
|
-
* @param {number} n Filled cells (clamped to [0, total])
|
|
227
|
-
* @param {number} total Total cells across the bar's logical range
|
|
228
|
-
* @param {object} [opts]
|
|
229
|
-
* @param {number} [opts.width=12] Cells in the bar (independent of n/total)
|
|
230
|
-
* @param {number[]} [opts.color] [r,g,b] tint for filled segment
|
|
231
|
-
* @param {string} [opts.label] Trailing label after the bar
|
|
232
|
-
* @param {string} [opts.fillGlyph='▰'] Override filled cell glyph
|
|
233
|
-
* @param {string} [opts.emptyGlyph='▱'] Override empty cell glyph
|
|
234
|
-
* @returns {string}
|
|
235
|
-
*/
|
|
236
|
-
function progressBar(n, total, opts) {
|
|
237
|
-
const o = opts || {};
|
|
238
|
-
const width = Math.max(1, o.width || 12);
|
|
239
|
-
const fillGlyph = o.fillGlyph || '▰';
|
|
240
|
-
const emptyGlyph = o.emptyGlyph || '▱';
|
|
241
|
-
const safeTotal = Math.max(1, total || 1);
|
|
242
|
-
const safeN = Math.max(0, Math.min(n || 0, safeTotal));
|
|
243
|
-
const filledCells = Math.round((safeN / safeTotal) * width);
|
|
244
|
-
const emptyCells = width - filledCells;
|
|
245
|
-
|
|
246
|
-
let bar = '';
|
|
247
|
-
if (filledCells > 0) {
|
|
248
|
-
const tint = Array.isArray(o.color) ? f(o.color[0], o.color[1], o.color[2]) : '';
|
|
249
|
-
const reset = tint ? R : '';
|
|
250
|
-
bar += `${tint}${fillGlyph.repeat(filledCells)}${reset}`;
|
|
251
|
-
}
|
|
252
|
-
if (emptyCells > 0) {
|
|
253
|
-
bar += `${D}${emptyGlyph.repeat(emptyCells)}${R}`;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const counter = ` ${safeN}/${safeTotal}`;
|
|
257
|
-
const label = o.label ? ` ${D}·${R} ${o.label}` : '';
|
|
258
|
-
return _maybePlain(bar + counter + label);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Subtitle: dim italic line under a banner. Single line.
|
|
263
|
-
*
|
|
264
|
-
* @param {string} text
|
|
265
|
-
* @param {object} [opts]
|
|
266
|
-
* @param {number[]} [opts.color] Optional tint
|
|
267
|
-
* @returns {string}
|
|
268
|
-
*/
|
|
269
|
-
function subtitle(text, opts) {
|
|
270
|
-
const o = opts || {};
|
|
271
|
-
const tint = Array.isArray(o.color) ? f(o.color[0], o.color[1], o.color[2]) : '';
|
|
272
|
-
return _maybePlain(` ${D}${I}${tint}${text}${R}`);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Em-dash rule line, tinted zen blue by default.
|
|
277
|
-
* ━━━ {text} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
278
|
-
*
|
|
279
|
-
* Use as a horizontal section separator anywhere in the system. Calling
|
|
280
|
-
* with no text produces a plain rule (just em-dashes, no label).
|
|
281
|
-
*
|
|
282
|
-
* @param {string} [text] Optional label to embed in the rule
|
|
283
|
-
* @param {object} [opts]
|
|
284
|
-
* @param {number} [opts.width=65] Total line width
|
|
285
|
-
* @param {number[]} [opts.color] [r,g,b] override tint; defaults to ZEN_BLUE
|
|
286
|
-
* @returns {string}
|
|
287
|
-
*/
|
|
288
|
-
function ruleLine(text, opts) {
|
|
289
|
-
const o = opts || {};
|
|
290
|
-
const width = o.width || 65;
|
|
291
|
-
const color = Array.isArray(o.color) ? o.color : ZEN_BLUE;
|
|
292
|
-
const tint = f(color[0], color[1], color[2]);
|
|
293
|
-
|
|
294
|
-
let line;
|
|
295
|
-
if (text && text.length > 0) {
|
|
296
|
-
const head = `━━━ ${text} `;
|
|
297
|
-
const padCount = Math.max(3, width - head.length);
|
|
298
|
-
line = head + '━'.repeat(padCount);
|
|
299
|
-
} else {
|
|
300
|
-
line = '━'.repeat(width);
|
|
301
|
-
}
|
|
302
|
-
return _maybePlain(`${tint}${line}${R}`);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Phase header: multi-line — badge, em-dash banner, progress bar.
|
|
307
|
-
* Concatenates with newlines so a single println prints all three.
|
|
308
|
-
*
|
|
309
|
-
* @param {number} n Phase number (1-based)
|
|
310
|
-
* @param {number} total Total phases
|
|
311
|
-
* @param {string} name Phase display name
|
|
312
|
-
* @param {string} bannerKey Banner registry key (e.g. 'north', 'forge')
|
|
313
|
-
* @param {object|string} [opts]
|
|
314
|
-
* Pass a string to use as the mode tint key ('fast' | 'full'),
|
|
315
|
-
* or an opts object with { mode, color, width }.
|
|
316
|
-
* @returns {string}
|
|
317
|
-
*/
|
|
318
|
-
function phaseHeader(n, total, name, bannerKey, opts) {
|
|
319
|
-
let o = {};
|
|
320
|
-
if (typeof opts === 'string') {
|
|
321
|
-
o = { mode: opts };
|
|
322
|
-
} else if (opts) {
|
|
323
|
-
o = opts;
|
|
324
|
-
}
|
|
325
|
-
const tint = o.color || (o.mode && MODE_TINTS[o.mode.toLowerCase()]) || null;
|
|
326
|
-
|
|
327
|
-
const bar = progressBar(n, total, {
|
|
328
|
-
width: o.width || 12,
|
|
329
|
-
color: tint,
|
|
330
|
-
label: name,
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
// Em-dash banner — match the existing format used across all forge commands,
|
|
334
|
-
// tinted zen blue for system-wide visual consistency on horizontal rules.
|
|
335
|
-
const emBanner = ruleLine(`Phase ${n}/${total} — ${name}`);
|
|
336
|
-
|
|
337
|
-
const lines = [
|
|
338
|
-
badge(bannerKey),
|
|
339
|
-
emBanner,
|
|
340
|
-
bar,
|
|
341
|
-
];
|
|
342
|
-
return lines.join('\n');
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* All available banner names.
|
|
347
|
-
* @returns {string[]}
|
|
348
|
-
*/
|
|
349
|
-
function list() {
|
|
350
|
-
return Object.keys(BANNERS);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Full gallery of all banners separated by rules.
|
|
355
|
-
* @returns {string}
|
|
356
|
-
*/
|
|
357
|
-
function gallery() {
|
|
358
|
-
return list().map((name, i) => {
|
|
359
|
-
const sep = i > 0 ? '\n' + rule() + '\n' : '';
|
|
360
|
-
return sep + render(name);
|
|
361
|
-
}).join('');
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// ─── Internal ──────────────────────────────────────────────────────────────────
|
|
365
|
-
|
|
366
|
-
function _get(name) {
|
|
367
|
-
const b = BANNERS[name.toLowerCase()];
|
|
368
|
-
if (!b) {
|
|
369
|
-
throw new Error(`Unknown banner "${name}". Available: ${list().join(', ')}`);
|
|
370
|
-
}
|
|
371
|
-
return b;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function _maybePlain(s) {
|
|
375
|
-
return (FORCE_PLAIN || isPlain()) ? stripAnsi(s) : s;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// ─── CLI ───────────────────────────────────────────────────────────────────────
|
|
379
|
-
// node banners.cjs [<name>] [--gallery] [--badge <name>] [--mark <name>] [--list]
|
|
380
|
-
|
|
381
|
-
if (require.main === module) {
|
|
382
|
-
let args = process.argv.slice(2);
|
|
383
|
-
|
|
384
|
-
// --plain may appear anywhere; consume it first.
|
|
385
|
-
const plainIdx = args.indexOf('--plain');
|
|
386
|
-
if (plainIdx !== -1) {
|
|
387
|
-
FORCE_PLAIN = true;
|
|
388
|
-
args = args.slice(0, plainIdx).concat(args.slice(plainIdx + 1));
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
try {
|
|
392
|
-
if (!args.length || args[0] === '--gallery') {
|
|
393
|
-
process.stdout.write(gallery() + '\n');
|
|
394
|
-
} else if (args[0] === '--list') {
|
|
395
|
-
console.log(list().map(n => {
|
|
396
|
-
const b = BANNERS[n];
|
|
397
|
-
return `${b.emoji} ${n.padEnd(8)} — ${b.tagline}`;
|
|
398
|
-
}).join('\n'));
|
|
399
|
-
} else if (args[0] === '--badge') {
|
|
400
|
-
console.log(badge(args[1] || ''));
|
|
401
|
-
} else if (args[0] === '--mark') {
|
|
402
|
-
console.log(mark(args[1] || ''));
|
|
403
|
-
} else if (args[0] === '--subtitle') {
|
|
404
|
-
console.log(subtitle(args.slice(1).join(' ')));
|
|
405
|
-
} else if (args[0] === '--progress') {
|
|
406
|
-
const n = Number(args[1]);
|
|
407
|
-
const total = Number(args[2]);
|
|
408
|
-
const label = args.slice(3).join(' ') || undefined;
|
|
409
|
-
console.log(progressBar(n, total, { label }));
|
|
410
|
-
} else if (args[0] === '--phase') {
|
|
411
|
-
const n = Number(args[1]);
|
|
412
|
-
const total = Number(args[2]);
|
|
413
|
-
const name = args[3] || '';
|
|
414
|
-
const bannerKey = args[4] || 'forge';
|
|
415
|
-
const mode = args[5]; // optional 'fast' | 'full'
|
|
416
|
-
console.log(phaseHeader(n, total, name, bannerKey, mode ? { mode } : undefined));
|
|
417
|
-
} else if (args[0] === '--rule') {
|
|
418
|
-
// --rule [text] Zen-blue em-dash horizontal rule (with optional label)
|
|
419
|
-
const text = args.slice(1).join(' ') || undefined;
|
|
420
|
-
console.log(ruleLine(text));
|
|
421
|
-
} else {
|
|
422
|
-
process.stdout.write(render(args[0]) + '\n');
|
|
423
|
-
}
|
|
424
|
-
} catch (e) {
|
|
425
|
-
console.error(e.message);
|
|
426
|
-
process.exit(1);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// ─── Exports ───────────────────────────────────────────────────────────────────
|
|
431
|
-
module.exports = {
|
|
432
|
-
render, badge, mark, list, gallery, rule, BANNERS,
|
|
433
|
-
progressBar, subtitle, phaseHeader, ruleLine,
|
|
434
|
-
isPlain, stripAnsi, MODE_TINTS, ZEN_BLUE,
|
|
435
|
-
};
|