@fprad0/skill-master-mcp 1.0.0 → 1.0.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +9 -3
  2. package/README.md +2 -2
  3. package/VERSION.md +4 -4
  4. package/bin/lib/client-config.mjs +11 -9
  5. package/bin/lib/menu-core.mjs +241 -70
  6. package/bin/skill-master-activation.mjs +3 -1
  7. package/bin/skill-master-menu.mjs +127 -17
  8. package/bin/skill-master-success-skills.mjs +52 -2
  9. package/docs/operations/assets/menu-frame-compact.html +78 -75
  10. package/docs/operations/assets/menu-frame-dna-hero.html +87 -0
  11. package/docs/operations/assets/menu-frame-fine-helix.html +89 -0
  12. package/docs/operations/assets/menu-frame-large.html +86 -83
  13. package/docs/operations/assets/menu-frame-running.html +82 -79
  14. package/docs/operations/assets/menu-frame-score-10-contact-sheet.html +184 -0
  15. package/docs/planning/mcp-1.0.0/00_RESUMO_EXECUTIVO_AUDITORIA_MENU.md +118 -0
  16. package/docs/planning/mcp-1.0.0/01_MATRIZ_TESTES_MENU_E_RESULTADOS.md +250 -0
  17. package/docs/planning/mcp-1.0.0/02_PLANO_CORRECAO_ATIVAR_SKILL_APRENDIDA.md +200 -0
  18. package/docs/planning/mcp-1.0.0/03_PLANO_COMPATIBILIDADE_WINDOWS_LINUX_MACOS.md +167 -0
  19. package/docs/planning/mcp-1.0.0/04_PLANO_UI_CYBERPUNK_PIXEL_ART_E_PERFORMANCE.md +165 -0
  20. package/docs/planning/mcp-1.0.0/05_PROMPT_TASK_EXECUCAO_CORRECOES.md +151 -0
  21. package/docs/planning/mcp-1.0.0/06_CHECKLIST_REGRESSAO_PRE_RELEASE.md +159 -0
  22. package/docs/planning/mcp-1.0.0/07_RELATORIO_APLICACAO_CORRECOES_MENU_SKILL_MASTER.md +136 -0
  23. package/docs/planning/mcp-1.0.0/08_AUDITORIA_CRITICA_MENU_NOTA_E_DNA_REFINADO.md +184 -0
  24. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/00_PROMPT_TASK_MASTER_NOTA_10_10.md +103 -0
  25. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/01_PROMPT_TASK_FINE_HELIX_DNA.md +116 -0
  26. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/02_PROMPT_TASK_DNA_HERO_BOOT_AND_MOTION.md +109 -0
  27. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/03_PROMPT_TASK_MENU_UX_HELP_ERROR_COPY.md +99 -0
  28. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/04_PROMPT_TASK_EVIDENCE_RENDERER_1_0_0.md +97 -0
  29. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/05_PROMPT_TASK_CROSS_PLATFORM_UTF8_MOJIBAKE.md +99 -0
  30. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/06_PROMPT_TASK_VISUAL_REGRESSION_QA.md +105 -0
  31. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/07_PROMPT_TASK_PRE_RELEASE_SCORE_GATE_10_10.md +104 -0
  32. package/docs/planning/mcp-1.0.0/prompt-tasks-nota-10-10/README_ORDEM_EXECUCAO_NOTA_10_10.md +77 -0
  33. package/manifests/channels/beta.json +7 -7
  34. package/manifests/channels/stable.json +8 -8
  35. package/package.json +16 -14
  36. package/scripts/render-menu-evidence.mjs +115 -49
  37. package/scripts/verify-menu-actions.mjs +13 -8
  38. package/scripts/verify-menu-visual.mjs +90 -0
@@ -1,54 +1,54 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { mkdirSync, writeFileSync } from 'node:fs';
3
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
4
  import { dirname, join, resolve } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
- import { buildMenuCommands, formatCyberMenuFrame, formatRunningActionFrame } from '../bin/lib/menu-core.mjs';
6
+ import {
7
+ buildMenuCommands,
8
+ formatCyberMenuFrame,
9
+ formatRunningActionFrame,
10
+ formatSkillMasterDnaHeroFrame,
11
+ getMenuStatus,
12
+ } from '../bin/lib/menu-core.mjs';
7
13
 
8
14
  const here = dirname(fileURLToPath(import.meta.url));
9
15
  const rootDir = resolve(here, '..');
10
16
  const outputDir = join(rootDir, 'docs', 'operations', 'assets');
17
+ const packageJson = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf8'));
18
+ const liveStatus = getMenuStatus(rootDir);
11
19
 
12
20
  const commands = buildMenuCommands({
13
- rootDir: '/tmp/skill-master',
14
- currentFile: '/tmp/skill-master/bin/skill-master-menu.mjs',
15
- nodeExecPath: '/usr/bin/node',
21
+ rootDir,
22
+ currentFile: join(rootDir, 'bin', 'skill-master-menu.mjs'),
23
+ nodeExecPath: process.execPath,
16
24
  });
17
25
 
18
26
  const baseStatus = {
19
- packageName: '@fprad0/skill-master-mcp',
20
- semver: '0.0.12',
21
- manifestVersion: '00.06',
22
- manifestSemver: '0.0.12',
27
+ ...liveStatus,
28
+ semver: packageJson.version,
29
+ manifestSemver: packageJson.version,
23
30
  versionText: '',
24
- rootDir: '/tmp/skill-master',
25
- pendingSuccessDrafts: 3,
26
- studyCandidates: 8,
31
+ pendingSuccessDrafts: Math.max(3, liveStatus.pendingSuccessDrafts),
32
+ studyCandidates: Math.max(8, liveStatus.studyCandidates),
27
33
  globalReadiness: {
34
+ ...liveStatus.globalReadiness,
28
35
  ready: true,
29
36
  mode: 'ready',
30
- required: 25,
31
- installed: Array.from({ length: 25 }, (_, index) => `skill-${index}`),
37
+ required: liveStatus.globalReadiness.required,
38
+ installed: Array.from(
39
+ { length: liveStatus.globalReadiness.required },
40
+ (_, index) => liveStatus.globalReadiness.installed[index] ?? `skill-${index + 1}`,
41
+ ),
32
42
  missing: [],
33
- codex: { present: true, kind: 'global', globalCommand: true },
34
- claude: { present: true, globalCommand: true },
35
- gemini: { present: true, globalCommand: true },
36
- antigravity: { present: true, globalCommand: true },
37
- },
38
- bundledCatalog: {
39
- total: 66,
40
- categories: [
41
- { key: 'moral', label: 'moral-core', count: 10 },
42
- { key: 'frontend', label: 'frontend-ui', count: 22 },
43
- { key: 'backend', label: 'backend-data', count: 19 },
44
- { key: 'ops', label: 'ops-clients', count: 12 },
45
- { key: 'knowledge', label: 'knowledge', count: 2 },
46
- ],
43
+ codex: { present: true, kind: 'absolute-node', globalCommand: true },
44
+ claude: { present: true, kind: 'absolute-node', globalCommand: true },
45
+ gemini: { present: true, kind: 'absolute-node', globalCommand: true },
46
+ antigravity: { present: true, kind: 'absolute-node', globalCommand: true },
47
47
  },
48
48
  };
49
49
 
50
50
  function stripAnsi(text) {
51
- return String(text).replace(/\x1b\[[0-9;?]*[A-Za-z]/g, '');
51
+ return String(text).replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, '');
52
52
  }
53
53
 
54
54
  function escapeHtml(text) {
@@ -67,12 +67,14 @@ function renderPage(title, frame) {
67
67
  <style>
68
68
  :root {
69
69
  color-scheme: dark;
70
- --bg: #060606;
71
- --panel: #0d0d0d;
72
- --grid: rgba(255,255,255,0.06);
73
- --line: rgba(255,255,255,0.25);
74
- --text: #f3f3f3;
75
- --muted: #8f949c;
70
+ --bg: #050708;
71
+ --panel: #0b1113;
72
+ --grid: rgba(112, 230, 229, 0.08);
73
+ --line: rgba(112, 230, 229, 0.34);
74
+ --text: #ecffff;
75
+ --muted: #9aa8ad;
76
+ --cyan: #70e6e5;
77
+ --amber: #e5c27a;
76
78
  }
77
79
  * { box-sizing: border-box; }
78
80
  body {
@@ -81,23 +83,24 @@ function renderPage(title, frame) {
81
83
  background:
82
84
  linear-gradient(var(--grid) 1px, transparent 1px),
83
85
  linear-gradient(90deg, var(--grid) 1px, transparent 1px),
84
- radial-gradient(circle at top, rgba(255,255,255,0.06), transparent 35%),
86
+ radial-gradient(circle at 70% 10%, rgba(112,230,229,0.13), transparent 36%),
87
+ radial-gradient(circle at 20% 80%, rgba(229,194,122,0.09), transparent 30%),
85
88
  var(--bg);
86
- background-size: 48px 48px, 48px 48px, auto, auto;
89
+ background-size: 42px 42px, 42px 42px, auto, auto, auto;
87
90
  color: var(--text);
88
91
  font-family: "Courier New", monospace;
89
92
  padding: 32px;
90
93
  }
91
94
  .frame {
92
95
  max-width: max-content;
93
- background: linear-gradient(180deg, rgba(255,255,255,0.03), rgba(255,255,255,0.01));
96
+ background: linear-gradient(180deg, rgba(112,230,229,0.05), rgba(255,255,255,0.01));
94
97
  border: 1px solid var(--line);
95
- box-shadow: 0 0 0 1px rgba(255,255,255,0.04), 0 24px 64px rgba(0,0,0,0.45);
98
+ box-shadow: 0 0 0 1px rgba(112,230,229,0.08), 0 24px 64px rgba(0,0,0,0.48);
96
99
  padding: 20px 24px;
97
100
  white-space: pre;
98
101
  line-height: 1.1;
99
102
  font-size: 13px;
100
- border-radius: 8px;
103
+ border-radius: 10px;
101
104
  }
102
105
  .title {
103
106
  margin: 0 0 16px;
@@ -115,16 +118,79 @@ function renderPage(title, frame) {
115
118
  </html>`;
116
119
  }
117
120
 
121
+ function renderContactSheet(items) {
122
+ const cards = items.map(({ title, frame }) => `
123
+ <section class="card">
124
+ <h2>${escapeHtml(title)}</h2>
125
+ <pre>${escapeHtml(stripAnsi(frame))}</pre>
126
+ </section>`).join('\n');
127
+
128
+ return `<!doctype html>
129
+ <html lang="pt-BR">
130
+ <head>
131
+ <meta charset="utf-8" />
132
+ <title>Skill Master Menu Evidence Contact Sheet</title>
133
+ <style>
134
+ :root { color-scheme: dark; --bg: #050708; --line: rgba(112,230,229,0.3); --text: #ecffff; --muted: #9aa8ad; }
135
+ body { margin: 0; background: var(--bg); color: var(--text); font-family: "Courier New", monospace; padding: 24px; }
136
+ h1 { font-size: 16px; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
137
+ .grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); align-items: start; }
138
+ .card { border: 1px solid var(--line); border-radius: 10px; padding: 14px; background: rgba(112,230,229,.035); overflow: auto; }
139
+ h2 { font-size: 12px; color: var(--muted); margin: 0 0 10px; text-transform: uppercase; letter-spacing: .1em; }
140
+ pre { margin: 0; white-space: pre; line-height: 1.08; font-size: 10px; }
141
+ </style>
142
+ </head>
143
+ <body>
144
+ <h1>Skill Master Menu Evidence - ${escapeHtml(packageJson.version)}</h1>
145
+ <main class="grid">${cards}</main>
146
+ </body>
147
+ </html>`;
148
+ }
149
+
118
150
  mkdirSync(outputDir, { recursive: true });
119
151
 
120
- const largeFrame = formatCyberMenuFrame(baseStatus, commands, 1, 8, { columns: 120, rows: 32, useColor: false });
121
- const compactFrame = formatCyberMenuFrame(baseStatus, commands, 20, 8, { columns: 96, rows: 24, useColor: false });
122
- const runningFrame = formatRunningActionFrame(baseStatus, commands.find((command) => command.key === 'doctor'), 5, { columns: 120, rows: 28, useColor: false });
152
+ const frames = [
153
+ {
154
+ file: 'menu-frame-large.html',
155
+ title: 'Menu Frame 120x32',
156
+ frame: formatCyberMenuFrame(baseStatus, commands, 1, 8, { columns: 120, rows: 32, useColor: false }),
157
+ },
158
+ {
159
+ file: 'menu-frame-compact.html',
160
+ title: 'Menu Frame 96x24',
161
+ frame: formatCyberMenuFrame(baseStatus, commands, 20, 8, { columns: 96, rows: 24, useColor: false }),
162
+ },
163
+ {
164
+ file: 'menu-frame-running.html',
165
+ title: 'Menu Running State',
166
+ frame: formatRunningActionFrame(baseStatus, commands.find((command) => command.key === 'doctor'), 5, { columns: 120, rows: 28, useColor: false }),
167
+ },
168
+ {
169
+ file: 'menu-frame-dna-hero.html',
170
+ title: 'DNA Hero Boot',
171
+ frame: formatSkillMasterDnaHeroFrame(baseStatus, 5, { columns: 120, rows: 32, useColor: false }),
172
+ },
173
+ {
174
+ file: 'menu-frame-fine-helix.html',
175
+ title: 'Fine Helix Focus',
176
+ frame: formatCyberMenuFrame(baseStatus, commands, commands.findIndex((command) => command.key === 'promptRecommendation'), 15, { columns: 120, rows: 34, useColor: false }),
177
+ },
178
+ ];
123
179
 
124
- writeFileSync(join(outputDir, 'menu-frame-large.html'), renderPage('Menu Frame 120x32', largeFrame), 'utf8');
125
- writeFileSync(join(outputDir, 'menu-frame-compact.html'), renderPage('Menu Frame 96x24', compactFrame), 'utf8');
126
- writeFileSync(join(outputDir, 'menu-frame-running.html'), renderPage('Menu Running State', runningFrame), 'utf8');
180
+ for (const item of frames) {
181
+ if (item.frame.includes('0.0.12')) {
182
+ throw new Error(`${item.file} contains stale version 0.0.12`);
183
+ }
184
+ writeFileSync(join(outputDir, item.file), renderPage(item.title, item.frame), 'utf8');
185
+ }
127
186
 
128
- console.log(join(outputDir, 'menu-frame-large.html'));
129
- console.log(join(outputDir, 'menu-frame-compact.html'));
130
- console.log(join(outputDir, 'menu-frame-running.html'));
187
+ writeFileSync(
188
+ join(outputDir, 'menu-frame-score-10-contact-sheet.html'),
189
+ renderContactSheet(frames),
190
+ 'utf8',
191
+ );
192
+
193
+ for (const item of frames) {
194
+ console.log(join(outputDir, item.file));
195
+ }
196
+ console.log(join(outputDir, 'menu-frame-score-10-contact-sheet.html'));
@@ -54,12 +54,16 @@ const READ_ONLY_ACTIONS = [
54
54
  'status',
55
55
  'doctor',
56
56
  'publicNpm',
57
- 'activationStatus',
58
- 'successNotifications',
59
- 'studySkills',
60
- 'approvalPackage',
61
- 'notionSummary',
62
- ];
57
+ 'activationStatus',
58
+ 'successNotifications',
59
+ 'studySkills',
60
+ 'notionSummary',
61
+ ];
62
+
63
+ const WRITES_LOCAL_ACTIONS = [
64
+ 'approvalPackage',
65
+ 'activateLearnedLocal',
66
+ ];
63
67
 
64
68
  const commands = buildMenuCommands({
65
69
  rootDir,
@@ -96,8 +100,9 @@ for (const key of READ_ONLY_ACTIONS) {
96
100
  console.log('Skill Master menu action verification');
97
101
  console.log(`- Actions: ${commands.length}`);
98
102
  console.log(`- Required actions: ${REQUIRED_ACTIONS.length}`);
99
- console.log(`- Read-only smoke candidates: ${READ_ONLY_ACTIONS.join(', ')}`);
100
- console.log(`- Confirmation protected: ${CONFIRMATION_REQUIRED.join(', ')}`);
103
+ console.log(`- Read-only smoke candidates: ${READ_ONLY_ACTIONS.join(', ')}`);
104
+ console.log(`- Local write actions: ${WRITES_LOCAL_ACTIONS.join(', ')}`);
105
+ console.log(`- Confirmation protected: ${CONFIRMATION_REQUIRED.join(', ')}`);
101
106
  console.log('');
102
107
 
103
108
  for (const command of commands) {
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync } from 'node:fs';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import {
7
+ buildMenuCommands,
8
+ formatCyberMenuFrame,
9
+ formatRunningActionFrame,
10
+ formatSkillMasterDnaHeroFrame,
11
+ getMenuStatus,
12
+ } from '../bin/lib/menu-core.mjs';
13
+
14
+ const here = dirname(fileURLToPath(import.meta.url));
15
+ const rootDir = resolve(here, '..');
16
+ const packageJson = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf8'));
17
+ const commands = buildMenuCommands({
18
+ rootDir,
19
+ currentFile: join(rootDir, 'bin', 'skill-master-menu.mjs'),
20
+ nodeExecPath: process.execPath,
21
+ });
22
+ const liveStatus = getMenuStatus(rootDir);
23
+ const status = {
24
+ ...liveStatus,
25
+ semver: packageJson.version,
26
+ manifestSemver: packageJson.version,
27
+ versionText: '',
28
+ globalReadiness: {
29
+ ...liveStatus.globalReadiness,
30
+ ready: true,
31
+ mode: 'ready',
32
+ missing: [],
33
+ installed: Array.from(
34
+ { length: liveStatus.globalReadiness.required },
35
+ (_, index) => liveStatus.globalReadiness.installed[index] ?? `skill-${index + 1}`,
36
+ ),
37
+ codex: { present: true, kind: 'absolute-node', globalCommand: true },
38
+ claude: { present: true, kind: 'absolute-node', globalCommand: true },
39
+ gemini: { present: true, kind: 'absolute-node', globalCommand: true },
40
+ antigravity: { present: true, kind: 'absolute-node', globalCommand: true },
41
+ },
42
+ };
43
+
44
+ function stripAnsi(text) {
45
+ return String(text).replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, '');
46
+ }
47
+
48
+ function assert(condition, message) {
49
+ if (!condition) throw new Error(message);
50
+ }
51
+
52
+ function assertMaxWidth(frame, width, label) {
53
+ for (const [index, line] of stripAnsi(frame).split('\n').entries()) {
54
+ assert(line.length <= width, `${label} line ${index + 1} exceeds ${width}: ${line.length}`);
55
+ }
56
+ }
57
+
58
+ function assertNoHeavyUnicode(frame, label) {
59
+ const plain = stripAnsi(frame);
60
+ assert(!/[┏┓┗┛╭╮╰╯╔╗╚╝┌┐└┘╾╼╴╶─═╍│▌▐▰▱█░▁▂▃▄▅▆▇·◢\u2800-\u28ff]/u.test(plain), `${label} contains premium Unicode in ASCII mode`);
61
+ }
62
+
63
+ const large = formatCyberMenuFrame(status, commands, 1, 8, { columns: 120, rows: 32, useColor: false });
64
+ const compact = formatCyberMenuFrame(status, commands, 20, 8, { columns: 96, rows: 24, useColor: false });
65
+ const running = formatRunningActionFrame(status, commands.find((command) => command.key === 'doctor'), 5, { columns: 120, rows: 28, useColor: false });
66
+ const hero = formatSkillMasterDnaHeroFrame(status, 5, { columns: 120, rows: 32, useColor: false });
67
+ const ascii = formatCyberMenuFrame(status, commands, 1, 8, { columns: 96, rows: 24, useColor: false, ascii: true });
68
+
69
+ assertMaxWidth(large, 120, 'large');
70
+ assertMaxWidth(compact, 96, 'compact');
71
+ assertMaxWidth(running, 120, 'running');
72
+ assertMaxWidth(hero, 120, 'dna-hero');
73
+ assertMaxWidth(ascii, 96, 'ascii');
74
+
75
+ assert(large.includes('DNA CYBER HELIX'), 'large frame missing DNA CYBER HELIX');
76
+ assert(large.includes('luminous fine helix'), 'large frame missing fine helix subtitle');
77
+ assert(hero.includes('SKILL_MASTER DNA ONLINE'), 'hero frame missing online title');
78
+ assert(hero.includes('DNA'), 'hero frame missing DNA label');
79
+ assert(hero.includes('ONLINE'), 'hero frame missing ONLINE state');
80
+ assert(compact.includes('DETAIL FOCUS'), 'compact frame missing details panel');
81
+ assert(compact.includes('DNA-CORE'), 'compact frame missing DNA panel');
82
+ assert(running.includes('SKILL_MASTER WORKFLOW ONLINE'), 'running frame missing running title');
83
+ assertNoHeavyUnicode(ascii, 'ascii frame');
84
+
85
+ for (const frame of [large, compact, running, hero, ascii]) {
86
+ assert(!frame.includes('0.0.12'), 'visual frame contains stale 0.0.12 version');
87
+ assert(!frame.includes('stable frame'), 'visual frame leaked old stable frame text');
88
+ }
89
+
90
+ console.log('verify-menu-visual: ok');