@fprad0/skill-master-mcp 0.0.7 → 0.0.8

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 CHANGED
@@ -7,6 +7,15 @@ All notable changes to `skill_master` will be tracked here.
7
7
  - Prepare a public npm publication path with dedicated workflow and operator guide.
8
8
  - Upgrade release automation from Node `20` to Node `22`.
9
9
 
10
+ ## [0.0.8] - 2026-06-27
11
+
12
+ - Add `skill_master_prompt_router` with `manual`, `balanced`, and `always-on-assisted` activation modes.
13
+ - Add Dev Senior Master persona routing, safety gates, Notion/update detection, and learned-skill signals.
14
+ - Add success-learning flows for human approval packages, local/global activation, study decisions, and rejection history.
15
+ - Add `skill-master-activation`, `skill-master-success-skills`, and `skill-master-eval-activation` operator CLIs.
16
+ - Expand the terminal menu with activation status, prompt recommendations, learned-skill notifications, study/reject actions, and Notion summaries.
17
+ - Add activation evals with positive, negative, and risk cases plus `npm run eval:activation`.
18
+
10
19
  ## [0.0.7] - 2026-06-26
11
20
 
12
21
  - Add a visual terminal menu for `skill-master-menu` using `prompts`, with TTY detection and direct action mode.
package/README.md CHANGED
@@ -108,18 +108,21 @@ npm install -g @fprad0/skill-master-mcp
108
108
  npx -y @fprad0/skill-master-mcp@latest
109
109
  ```
110
110
 
111
- Estado atual validado em `2026-06-26`:
111
+ Estado atual preparado em `2026-06-27`:
112
112
 
113
- - pacote publico publicado: `@fprad0/skill-master-mcp@0.0.7`
114
- - dist-tag `latest` apontando para `0.0.7`
115
- - workflow `Publish Skill Master to npmjs` concluido com sucesso
116
- - `npm install` e `npx` confirmados
113
+ - release local preparada: `@fprad0/skill-master-mcp@0.0.8`
114
+ - validacao de pacote por tarball local confirmada
115
+ - publicacao no npmjs aguardando autenticacao npmjs nesta maquina
116
+ - apos publicar, validar `npm install`, `npx` e dist-tag `latest`
117
117
 
118
118
  Comandos globais principais:
119
119
 
120
120
  ```bash
121
+ skill-master-activation
122
+ skill-master-eval-activation
121
123
  skill-master-mcp
122
124
  skill-master-menu
125
+ skill-master-success-skills
123
126
  skill-master-update
124
127
  skill-master-configure-private-registry
125
128
  ```
@@ -136,10 +139,38 @@ O menu agora possui modo visual interativo para terminal com TTY e tambem aceita
136
139
  skill-master-menu --run status
137
140
  skill-master-menu --run check
138
141
  skill-master-menu --run update --yes
142
+ skill-master-menu --run notifications
143
+ skill-master-menu --run study-skills
144
+ skill-master-menu --run approval-package
145
+ skill-master-menu --run activation-status
146
+ skill-master-menu --run recommend-prompt
147
+ skill-master-menu --run notion-summary
139
148
  ```
140
149
 
141
150
  O menu visual usa `prompts` para ficar mais legivel no terminal e manter compatibilidade com `Node 18+`.
142
151
 
152
+ O menu tambem mostra notificacoes de skills aprendidas pendentes e links externos para estudo. As acoes de ativacao sao:
153
+
154
+ - `skill-master-menu --run activate-learned-local`: instala uma skill aprovada em `.codex/skills` do workspace atual.
155
+ - `skill-master-menu --run activate-learned-global`: instala uma skill aprovada em `${CODEX_HOME:-~/.codex}/skills`.
156
+ - `skill-master-menu --run mark-study`: registra uma skill candidata como material para estudo.
157
+ - `skill-master-menu --run reject-skill`: rejeita uma skill candidata preservando historico.
158
+
159
+ Para modo de ativacao e recomendacao local:
160
+
161
+ ```bash
162
+ skill-master-activation --status
163
+ skill-master-activation --set-mode balanced
164
+ skill-master-activation --route-prompt "skill-master, recomende skills para este prompt"
165
+ skill-master-activation --notion-summary
166
+ ```
167
+
168
+ Para rodar as avaliacoes de ativacao antes de release:
169
+
170
+ ```bash
171
+ npm run eval:activation
172
+ ```
173
+
143
174
  Para atualizar a instalacao global via npm sem iniciar o servidor MCP:
144
175
 
145
176
  ```bash
@@ -200,18 +231,62 @@ O `skill_master` pode aprender com as skills ja existentes em cada maquina insta
200
231
  Ferramentas MCP principais:
201
232
 
202
233
  - `skill_master_refresh_catalog`
234
+ - `skill_master_prompt_router`
235
+ - `skill_master_activation_check`
236
+ - `skill_master_recommend`
203
237
  - `skill_master_prepare_skill_contribution`
204
238
  - `skill_master_review_skill_contribution`
239
+ - `skill_master_prepare_success_skill`
240
+ - `skill_master_review_success_skill`
241
+ - `skill_master_list_unapproved_success_skills`
242
+ - `skill_master_prepare_success_skill_approval_package`
243
+ - `skill_master_activate_success_skill`
205
244
 
206
245
  O pacote de contribuicao nao envia arquivos automaticamente, nao executa skills desconhecidas e nao inclui caminhos completos ou corpo bruto por padrao.
207
246
 
247
+ O fluxo de aprendizado por implementacoes bem-sucedidas cria rascunhos locais em staging, gera pacote de aprovacao humana e permite ativacao explicita em escopo local ou global. Ele exige evidencias, revisa risco/duplicidade e mantem candidatos externos como nao aprovados ate revisao humana. Nenhuma skill aprendida e publicada automaticamente.
248
+
208
249
  Leia:
209
250
 
210
251
  - [Rede segura de skills](docs/architecture/REDE_SEGURA_DE_SKILLS.md)
252
+ - [Aprendizado de implementacoes bem-sucedidas](docs/architecture/APRENDIZADO_DE_IMPLEMENTACOES_BEM_SUCEDIDAS.md)
211
253
 
212
254
  ## Modos de ativacao em prompts
213
255
 
214
- A partir da versao `0.0.4`, clientes e agentes podem usar `skill_master_activation_check` antes de decidir se devem acionar recomendacoes de skills.
256
+ Clientes e agentes podem usar `skill_master_prompt_router` como camada principal antes de decidir se devem acionar recomendacoes de skills, aplicar persona ou bloquear uma acao sensivel.
257
+
258
+ Modos suportados:
259
+
260
+ - `manual`: ativa apenas com mencao direta ao Skill Master ou gate bloqueante.
261
+ - `balanced`: modo recomendado; ativa por mencao direta, tarefa tecnica com skill relevante, Notion, aprendizado, validacao, MCP ou publicacao.
262
+ - `always-on-assisted`: avalia quase todo prompt, mas retorna `executionMode: no-op` quando nao houver ganho claro.
263
+
264
+ Exemplo de chamada conceitual:
265
+
266
+ ```json
267
+ {
268
+ "prompt": "skill-master, veja se existe uma skill para validar este deploy",
269
+ "activationMode": "balanced",
270
+ "riskTolerance": "normal"
271
+ }
272
+ ```
273
+
274
+ Saida esperada:
275
+
276
+ ```json
277
+ {
278
+ "shouldActivate": true,
279
+ "personaOverlay": "Dev Senior Master",
280
+ "executionMode": "assist",
281
+ "safetyGates": [],
282
+ "learningOpportunity": false,
283
+ "notionUpdateNeeded": false
284
+ }
285
+ ```
286
+
287
+ Use `skill_master_activation_check` quando precisar apenas de uma decisao menor e retrocompativel de ativacao/recomendacao.
288
+
289
+ Restricoes explicitas como `sem publicar`, `nao publicar` ou `nao publique` sao tratadas como execucao local. O router deve registrar `publication_explicitly_disabled` e nao pode transformar essa frase em autorizacao ou intencao de release.
215
290
 
216
291
  Ativacao explicita:
217
292
 
@@ -241,6 +316,11 @@ Cliente: chama skill_master_activation_check.
241
316
  Cliente: se ativar, chama skill_master_recommend ou segue as recomendacoes retornadas.
242
317
  ```
243
318
 
319
+ Diagnostico importante:
320
+
321
+ - `skill_master_list_sources` mostra `configPath`, `workspace` e se `workspaceRoots` esta configurado.
322
+ - Se `workspaceRoots` estiver vazio, skills em `.codex/skills` do projeto nao serao catalogadas ate atualizar `sources.json` e reiniciar o processo MCP.
323
+
244
324
  ## Atualizacao automatica via npm
245
325
 
246
326
  Para instalacoes feitas por `npm install -g`, o caminho seguro de auto-update e executar `skill-master-update` fora do processo MCP.
package/VERSION.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Versão funcional planejada: `00.02`
4
4
 
5
- Versão técnica para empacotamento semântico: `0.0.7`
5
+ Versão técnica para empacotamento semântico: `0.0.8`
6
6
 
7
7
  ## Observação
8
8
 
9
- O nome `00.02` será usado na comunicação e nos documentos. Para ferramentas que exigem SemVer, como npm e alguns fluxos de release, usar `0.0.7`.
9
+ O nome `00.02` será usado na comunicação e nos documentos. Para ferramentas que exigem SemVer, como npm e alguns fluxos de release, usar `0.0.8`.
@@ -1,5 +1,5 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { existsSync, readFileSync } from 'node:fs';
2
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  import process from 'node:process';
5
5
 
@@ -39,6 +39,9 @@ export function getMenuStatus(rootDir) {
39
39
  const packageJson = readJson(rootDir, 'package.json');
40
40
  const stableManifest = readJson(rootDir, 'manifests/channels/stable.json');
41
41
  const versionText = readText(rootDir, 'VERSION.md');
42
+ const successLearningDir = process.env.SKILL_MASTER_SUCCESS_LEARNING_DIR
43
+ ?? join(process.env.SKILL_MASTER_HOME ?? join(process.env.HOME ?? process.env.USERPROFILE ?? '', '.skill-master'), 'data', 'success-learning');
44
+ const studyCandidates = readJson(rootDir, 'network/unapproved-skill-candidates.json');
42
45
 
43
46
  return {
44
47
  packageName: packageJson?.name ?? 'nao encontrado',
@@ -47,9 +50,29 @@ export function getMenuStatus(rootDir) {
47
50
  manifestSemver: stableManifest?.semver ?? 'nao encontrado',
48
51
  versionText,
49
52
  rootDir,
53
+ pendingSuccessDrafts: countManifestFiles(successLearningDir),
54
+ studyCandidates: Array.isArray(studyCandidates?.candidates) ? studyCandidates.candidates.length : 0,
50
55
  };
51
56
  }
52
57
 
58
+ function countManifestFiles(directory) {
59
+ if (!directory || !existsSync(directory)) {
60
+ return 0;
61
+ }
62
+
63
+ let count = 0;
64
+ const visit = (current) => {
65
+ for (const entry of readdirSync(current, { withFileTypes: true })) {
66
+ const fullPath = join(current, entry.name);
67
+ if (entry.isDirectory()) visit(fullPath);
68
+ else if (entry.isFile() && entry.name === 'manifest.json') count += 1;
69
+ }
70
+ };
71
+
72
+ visit(directory);
73
+ return count;
74
+ }
75
+
53
76
  export function buildMenuCommands({ rootDir, currentFile, nodeExecPath = process.execPath }) {
54
77
  return [
55
78
  {
@@ -107,6 +130,106 @@ export function buildMenuCommands({ rootDir, currentFile, nodeExecPath = process
107
130
  args: ['scripts/configure-private-registry.mjs', '--validate'],
108
131
  confirmMessage: 'Rodar a configuracao de registry privado agora?',
109
132
  },
133
+ {
134
+ key: 'activationStatus',
135
+ aliases: ['activation-status', 'modo', 'modo-ativacao'],
136
+ label: 'Modo de ativacao atual',
137
+ description: 'Mostra o modo manual, balanced ou always-on-assisted configurado localmente.',
138
+ command: nodeExecPath,
139
+ args: [join(rootDir, 'bin', 'skill-master-activation.mjs'), '--status'],
140
+ },
141
+ {
142
+ key: 'activationBalanced',
143
+ aliases: ['set-balanced', 'balanced'],
144
+ label: 'Usar modo balanced',
145
+ description: 'Define balanced como modo padrao de ativacao do Skill Master.',
146
+ command: nodeExecPath,
147
+ args: [join(rootDir, 'bin', 'skill-master-activation.mjs'), '--set-mode', 'balanced'],
148
+ },
149
+ {
150
+ key: 'activationAlwaysOn',
151
+ aliases: ['set-always-on', 'always-on-assisted'],
152
+ label: 'Usar modo always-on-assisted',
153
+ description: 'Define avaliacao assistida quase sempre ativa, mantendo no-op quando nao houver ganho.',
154
+ command: nodeExecPath,
155
+ args: [join(rootDir, 'bin', 'skill-master-activation.mjs'), '--set-mode', 'always-on-assisted'],
156
+ confirmMessage: 'Alterar o modo local para always-on-assisted?',
157
+ },
158
+ {
159
+ key: 'promptRecommendation',
160
+ aliases: ['recommend-prompt', 'recomendar-prompt', 'prompt-router'],
161
+ label: 'Ver recomendacao para um prompt',
162
+ description: 'Abre um fluxo interativo para avaliar um prompt pelo router local.',
163
+ command: nodeExecPath,
164
+ args: [join(rootDir, 'bin', 'skill-master-activation.mjs'), '--route-prompt-interactive'],
165
+ },
166
+ {
167
+ key: 'successNotifications',
168
+ aliases: ['notifications', 'notificacoes', 'success-notifications'],
169
+ label: 'Notificacoes de skills aprendidas',
170
+ description: 'Mostra drafts pendentes, aprovacoes e skills externas para estudar.',
171
+ command: nodeExecPath,
172
+ args: [join(rootDir, 'bin', 'skill-master-success-skills.mjs'), '--notify'],
173
+ },
174
+ {
175
+ key: 'studySkills',
176
+ aliases: ['study-skills', 'skills-estudo', 'estudar'],
177
+ label: 'Skills para estudar',
178
+ description: 'Lista skills externas e links de criadores ainda nao aprovados.',
179
+ command: nodeExecPath,
180
+ args: [join(rootDir, 'bin', 'skill-master-success-skills.mjs'), '--study'],
181
+ },
182
+ {
183
+ key: 'approvalPackage',
184
+ aliases: ['approval-package', 'aprovar', 'pacote-aprovacao'],
185
+ label: 'Gerar pacote de aprovacao humana',
186
+ description: 'Cria um relatorio local para revisar e aprovar skills aprendidas.',
187
+ command: nodeExecPath,
188
+ args: [join(rootDir, 'bin', 'skill-master-success-skills.mjs'), '--approval-package'],
189
+ },
190
+ {
191
+ key: 'markLearnedStudy',
192
+ aliases: ['mark-study', 'manter-estudo'],
193
+ label: 'Manter skill candidata para estudo',
194
+ description: 'Seleciona uma candidata e registra decisao de manter para estudo.',
195
+ command: nodeExecPath,
196
+ args: [join(rootDir, 'bin', 'skill-master-success-skills.mjs'), '--mark-study-interactive'],
197
+ },
198
+ {
199
+ key: 'rejectLearnedSkill',
200
+ aliases: ['reject-skill', 'rejeitar-skill'],
201
+ label: 'Rejeitar skill candidata',
202
+ description: 'Seleciona uma candidata, registra rejeicao e preserva historico.',
203
+ command: nodeExecPath,
204
+ args: [join(rootDir, 'bin', 'skill-master-success-skills.mjs'), '--reject-interactive'],
205
+ confirmMessage: 'Abrir fluxo para rejeitar uma skill candidata?',
206
+ },
207
+ {
208
+ key: 'activateLearnedLocal',
209
+ aliases: ['activate-learned-local', 'ativar-local', 'skill-local'],
210
+ label: 'Ativar skill aprendida no workspace',
211
+ description: 'Instala uma skill aprendida em .codex/skills do projeto atual.',
212
+ command: nodeExecPath,
213
+ args: [join(rootDir, 'bin', 'skill-master-success-skills.mjs'), '--activate-interactive', '--target', 'local'],
214
+ confirmMessage: 'Selecionar e ativar uma skill aprendida no workspace atual?',
215
+ },
216
+ {
217
+ key: 'activateLearnedGlobal',
218
+ aliases: ['activate-learned-global', 'ativar-global', 'skill-global'],
219
+ label: 'Ativar skill aprendida global',
220
+ description: 'Instala uma skill aprendida em CODEX_HOME/skills ou ~/.codex/skills.',
221
+ command: nodeExecPath,
222
+ args: [join(rootDir, 'bin', 'skill-master-success-skills.mjs'), '--activate-interactive', '--target', 'global'],
223
+ confirmMessage: 'Selecionar e ativar uma skill aprendida como skill global deste usuario?',
224
+ },
225
+ {
226
+ key: 'notionSummary',
227
+ aliases: ['notion-summary', 'resumo-notion'],
228
+ label: 'Abrir resumo para Notion',
229
+ description: 'Mostra um resumo copiavel do estado de ativacao para registrar no ledger Notion.',
230
+ command: nodeExecPath,
231
+ args: [join(rootDir, 'bin', 'skill-master-activation.mjs'), '--notion-summary'],
232
+ },
110
233
  ];
111
234
  }
112
235
 
@@ -145,6 +268,8 @@ export function formatStatusReport(status) {
145
268
  `Semver local: ${status.semver}`,
146
269
  `Manifesto stable: ${status.manifestVersion}`,
147
270
  `Manifesto semver: ${status.manifestSemver}`,
271
+ `Drafts de skills aprendidas: ${status.pendingSuccessDrafts}`,
272
+ `Skills externas para estudar: ${status.studyCandidates}`,
148
273
  ];
149
274
 
150
275
  if (status.versionText) {
@@ -168,6 +293,7 @@ export function formatMenuBanner(status, { useColor = false } = {}) {
168
293
  colorize('Skill Master MCP', ANSI.bold, useColor),
169
294
  'Menu operacional para manutencao local',
170
295
  `Versao local ${status.semver} | canal ${status.manifestVersion}`,
296
+ `Pendencias: ${status.pendingSuccessDrafts} drafts | estudo: ${status.studyCandidates} links`,
171
297
  colorize('Setas + Enter para navegar', ANSI.dim, useColor),
172
298
  ];
173
299
  return renderPanelLines(lines, { color: ANSI.cyan, useColor });
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import process from 'node:process';
7
+ import { fileURLToPath } from 'node:url';
8
+ import prompts from 'prompts';
9
+ import { buildCatalog, loadConfig } from '../dist/catalog.js';
10
+ import { routeSkillMasterPrompt } from '../dist/prompt-router.js';
11
+
12
+ const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
13
+ const skillMasterHome = process.env.SKILL_MASTER_HOME ?? path.join(os.homedir(), '.skill-master');
14
+ const activationConfigPath = process.env.SKILL_MASTER_ACTIVATION_CONFIG
15
+ ?? path.join(skillMasterHome, 'activation.json');
16
+ const sourcesConfigPath = process.env.SKILL_MASTER_CONFIG ?? path.join(rootDir, 'sources.json');
17
+ const workspace = process.env.SKILL_MASTER_WORKSPACE ?? process.cwd();
18
+
19
+ const defaultConfig = {
20
+ activationMode: 'balanced',
21
+ riskTolerance: 'normal',
22
+ };
23
+
24
+ const isTty = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
25
+
26
+ const readActivationConfig = () => {
27
+ if (!existsSync(activationConfigPath)) return defaultConfig;
28
+ return { ...defaultConfig, ...JSON.parse(readFileSync(activationConfigPath, 'utf8')) };
29
+ };
30
+
31
+ const writeActivationConfig = (config) => {
32
+ mkdirSync(path.dirname(activationConfigPath), { recursive: true });
33
+ writeFileSync(activationConfigPath, JSON.stringify(config, null, 2), 'utf8');
34
+ };
35
+
36
+ const parseArgs = (argv) => {
37
+ const parsed = {
38
+ command: 'status',
39
+ mode: null,
40
+ prompt: null,
41
+ format: 'markdown',
42
+ };
43
+
44
+ for (let index = 0; index < argv.length; index += 1) {
45
+ const arg = argv[index];
46
+ if (arg === '--status') parsed.command = 'status';
47
+ else if (arg === '--set-mode') {
48
+ parsed.command = 'set-mode';
49
+ parsed.mode = argv[++index] ?? null;
50
+ } else if (arg === '--route-prompt') {
51
+ parsed.command = 'route-prompt';
52
+ parsed.prompt = argv[++index] ?? null;
53
+ } else if (arg === '--route-prompt-interactive') parsed.command = 'route-prompt-interactive';
54
+ else if (arg === '--notion-summary') parsed.command = 'notion-summary';
55
+ else if (arg === '--json') parsed.format = 'json';
56
+ else if (arg === '--help' || arg === '-h') parsed.command = 'help';
57
+ else throw new Error(`Unknown argument: ${arg}`);
58
+ }
59
+
60
+ return parsed;
61
+ };
62
+
63
+ const loadSkills = async () => {
64
+ const config = await loadConfig(sourcesConfigPath);
65
+ const catalog = await buildCatalog(config, { cwd: workspace, includeWeb: false });
66
+ return catalog.skills;
67
+ };
68
+
69
+ const routePrompt = async (prompt, { format }) => {
70
+ if (!prompt) throw new Error('Missing prompt.');
71
+ const config = readActivationConfig();
72
+ const skills = await loadSkills();
73
+ const decision = routeSkillMasterPrompt(skills, prompt, {
74
+ activationMode: config.activationMode,
75
+ riskTolerance: config.riskTolerance,
76
+ limit: 8,
77
+ sourceKinds: ['workspace', 'local', 'plugin'],
78
+ });
79
+
80
+ if (format === 'json') {
81
+ console.log(JSON.stringify(decision, null, 2));
82
+ return;
83
+ }
84
+
85
+ console.log('Skill Master - prompt router');
86
+ console.log(`- Ativar: ${decision.shouldActivate ? 'sim' : 'nao'}`);
87
+ console.log(`- Modo: ${decision.activationMode}`);
88
+ console.log(`- Execucao: ${decision.executionMode}`);
89
+ console.log(`- Persona: ${decision.personaOverlay}`);
90
+ console.log(`- Proxima acao: ${decision.nextAction}`);
91
+ if (decision.recommendedSkills.length > 0) {
92
+ console.log('- Skills:');
93
+ for (const skill of decision.recommendedSkills.slice(0, 5)) {
94
+ console.log(` - ${skill.name} (${skill.source})`);
95
+ }
96
+ }
97
+ };
98
+
99
+ const printStatus = () => {
100
+ const config = readActivationConfig();
101
+ console.log('Skill Master - modo de ativacao');
102
+ console.log(`- Config: ${activationConfigPath}`);
103
+ console.log(`- Modo: ${config.activationMode}`);
104
+ console.log(`- Tolerancia de risco: ${config.riskTolerance}`);
105
+ console.log(`- Workspace: ${workspace}`);
106
+ };
107
+
108
+ const setMode = (mode) => {
109
+ if (!['manual', 'balanced', 'always-on-assisted'].includes(mode)) {
110
+ throw new Error('Mode must be manual, balanced, or always-on-assisted.');
111
+ }
112
+ const config = { ...readActivationConfig(), activationMode: mode };
113
+ writeActivationConfig(config);
114
+ console.log(`Modo de ativacao atualizado para: ${mode}`);
115
+ };
116
+
117
+ const routePromptInteractive = async (format) => {
118
+ if (!isTty()) throw new Error('Interactive prompt routing requires a TTY.');
119
+ const response = await prompts({
120
+ type: 'text',
121
+ name: 'prompt',
122
+ message: 'Qual prompt voce quer avaliar?',
123
+ validate: (value) => value.trim().length >= 3 || 'Informe ao menos 3 caracteres.',
124
+ });
125
+ await routePrompt(response.prompt, { format });
126
+ };
127
+
128
+ const printNotionSummary = () => {
129
+ const config = readActivationConfig();
130
+ console.log('## Resumo para Notion - Skill Master Activation');
131
+ console.log('');
132
+ console.log(`- Modo atual: ${config.activationMode}`);
133
+ console.log(`- Tolerancia de risco: ${config.riskTolerance}`);
134
+ console.log(`- Workspace: ${workspace}`);
135
+ console.log('- Politica: nenhuma publicacao sem autorizacao explicita.');
136
+ console.log('- Recomendacao: registrar mudancas de modo, decisoes de skills aprendidas e releases pendentes no ledger do Skill Master.');
137
+ };
138
+
139
+ const printHelp = () => {
140
+ console.log(`Skill Master Activation
141
+
142
+ Usage:
143
+ skill-master-activation --status
144
+ skill-master-activation --set-mode manual|balanced|always-on-assisted
145
+ skill-master-activation --route-prompt "prompt" [--json]
146
+ skill-master-activation --route-prompt-interactive
147
+ skill-master-activation --notion-summary
148
+ `);
149
+ };
150
+
151
+ try {
152
+ const args = parseArgs(process.argv.slice(2));
153
+ if (args.command === 'help') printHelp();
154
+ else if (args.command === 'status') printStatus();
155
+ else if (args.command === 'set-mode') setMode(args.mode);
156
+ else if (args.command === 'route-prompt') await routePrompt(args.prompt, { format: args.format });
157
+ else if (args.command === 'route-prompt-interactive') await routePromptInteractive(args.format);
158
+ else if (args.command === 'notion-summary') printNotionSummary();
159
+ else throw new Error(`Unsupported command: ${args.command}`);
160
+ } catch (error) {
161
+ process.stderr.write(`[skill_master] ${error instanceof Error ? error.message : String(error)}\n`);
162
+ process.exitCode = 1;
163
+ }
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runActivationEvals } from '../dist/activation-evals.js';
4
+
5
+ const report = runActivationEvals();
6
+ const asJson = process.argv.includes('--json');
7
+
8
+ if (asJson) {
9
+ console.log(JSON.stringify(report, null, 2));
10
+ } else {
11
+ console.log('Skill Master Activation Evals');
12
+ console.log(`- Generated at: ${report.generatedAt}`);
13
+ console.log(`- Total: ${report.total}`);
14
+ console.log(`- Passed: ${report.passed}`);
15
+ console.log(`- Failed: ${report.failed}`);
16
+ console.log(`- Accuracy: ${(report.accuracy * 100).toFixed(1)}%`);
17
+ console.log(`- False positives: ${report.falsePositives}`);
18
+ console.log(`- False negatives: ${report.falseNegatives}`);
19
+ console.log(`- Correct blocks: ${report.correctBlocks}`);
20
+ console.log(`- Recommendation: ${report.recommendation}`);
21
+
22
+ const failed = report.results.filter((result) => !result.passed);
23
+ if (failed.length > 0) {
24
+ console.log('');
25
+ console.log('Failed cases:');
26
+ for (const result of failed) {
27
+ console.log(`- ${result.case.id}: ${result.findings.join('; ')}`);
28
+ }
29
+ }
30
+ }
31
+
32
+ process.exitCode = report.recommendation === 'balanced-ready' ? 0 : 1;