shakers-cli-beta 0.8.0-beta.0
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/LICENSE +59 -0
- package/README.md +1175 -0
- package/bin/add-agent.js +88 -0
- package/bin/add-project.js +88 -0
- package/bin/add-role.js +61 -0
- package/bin/add-skill.js +88 -0
- package/bin/ai-usage.js +81 -0
- package/bin/alma.js +99 -0
- package/bin/applications.js +69 -0
- package/bin/availability.js +70 -0
- package/bin/certifications.js +69 -0
- package/bin/certify.js +73 -0
- package/bin/change-role.js +61 -0
- package/bin/config.js +120 -0
- package/bin/experiences.js +69 -0
- package/bin/find-projects.js +89 -0
- package/bin/invitations.js +69 -0
- package/bin/lang.js +70 -0
- package/bin/login.js +283 -0
- package/bin/mcp.js +98 -0
- package/bin/me.js +69 -0
- package/bin/onboarding.js +134 -0
- package/bin/portfolios.js +69 -0
- package/bin/rate.js +70 -0
- package/bin/register.js +325 -0
- package/bin/report-html.js +134 -0
- package/bin/save.js +77 -0
- package/bin/shakers.js +344 -0
- package/bin/share.js +72 -0
- package/bin/show-project.js +72 -0
- package/bin/socials.js +70 -0
- package/bin/superadmin.js +351 -0
- package/package.json +40 -0
- package/src/agent-category.js +13 -0
- package/src/agent-evaluation.js +177 -0
- package/src/agent-org-chart.js +355 -0
- package/src/agent-synthesis.js +132 -0
- package/src/agent-usage.js +118 -0
- package/src/agents-client.js +165 -0
- package/src/ai-fluency-cell.js +72 -0
- package/src/ai-profile-client.js +45 -0
- package/src/ai-profile-preview.js +154 -0
- package/src/ai.js +66 -0
- package/src/alma-client.js +123 -0
- package/src/alma-flow.js +32 -0
- package/src/alma-repo-context.js +47 -0
- package/src/alma-shell.js +161 -0
- package/src/ansi.js +62 -0
- package/src/applications-client.js +79 -0
- package/src/applications-flow.js +58 -0
- package/src/auth-client.js +144 -0
- package/src/auth-device-client.js +118 -0
- package/src/auth-method-picker.js +44 -0
- package/src/auth-methods.js +35 -0
- package/src/auth-session-store.js +214 -0
- package/src/authorship.js +203 -0
- package/src/automations-detector.js +170 -0
- package/src/availability-client.js +92 -0
- package/src/availability-flow.js +105 -0
- package/src/backend-request.js +170 -0
- package/src/blind-approval-extract.js +48 -0
- package/src/brand-ansi.js +14 -0
- package/src/brand-svg.js +9 -0
- package/src/browser-tools-detector.js +21 -0
- package/src/build-next-level.js +56 -0
- package/src/certifications-client.js +89 -0
- package/src/certifications-flow.js +75 -0
- package/src/certify-dimension-client.js +217 -0
- package/src/certify-dimension-flow.js +193 -0
- package/src/certify-disclaimer.js +51 -0
- package/src/certify-remediation-prompt.js +23 -0
- package/src/cli-args.js +83 -0
- package/src/config-dir.js +120 -0
- package/src/config.js +778 -0
- package/src/consent-flow.js +115 -0
- package/src/consent-skip.js +27 -0
- package/src/decisions-extract.js +43 -0
- package/src/detect-repos.js +145 -0
- package/src/detected-tools.js +15 -0
- package/src/detection-evidence.js +105 -0
- package/src/detection-noise.js +132 -0
- package/src/detectors.js +221 -0
- package/src/device-auth-store.js +100 -0
- package/src/device-login.js +118 -0
- package/src/email-verification.js +152 -0
- package/src/env-paths.js +16 -0
- package/src/find-projects-cache.js +89 -0
- package/src/find-projects-client.js +138 -0
- package/src/find-projects-flow.js +164 -0
- package/src/git-activity.js +123 -0
- package/src/graph-certs.js +58 -0
- package/src/graph-generator.js +230 -0
- package/src/graph-scan.js +239 -0
- package/src/i18n.js +3264 -0
- package/src/inter-fonts.js +6 -0
- package/src/interactive-select.js +183 -0
- package/src/interview-client.js +226 -0
- package/src/interview-transcript.js +56 -0
- package/src/inventory-client.js +90 -0
- package/src/invitations-client.js +66 -0
- package/src/invitations-flow.js +50 -0
- package/src/lang-client.js +147 -0
- package/src/lang-codes.js +14 -0
- package/src/lang-flow.js +85 -0
- package/src/legal-notice.js +53 -0
- package/src/locale.js +51 -0
- package/src/markdown-ansi.js +50 -0
- package/src/maturity.js +111 -0
- package/src/mcp-ai-usage-result-tool.js +109 -0
- package/src/mcp-ai-usage-tool.js +333 -0
- package/src/mcp-alma-tools.js +91 -0
- package/src/mcp-applications-tools.js +42 -0
- package/src/mcp-ask-tools.js +50 -0
- package/src/mcp-auth-form.js +282 -0
- package/src/mcp-availability-tools.js +43 -0
- package/src/mcp-certifications-tools.js +42 -0
- package/src/mcp-certify-dimension-tools.js +58 -0
- package/src/mcp-detector.js +223 -0
- package/src/mcp-device-login-tools.js +173 -0
- package/src/mcp-find-projects-tools.js +67 -0
- package/src/mcp-install.js +245 -0
- package/src/mcp-invitations-tools.js +42 -0
- package/src/mcp-lang-tools.js +39 -0
- package/src/mcp-onboarding-tools.js +388 -0
- package/src/mcp-portfolios-tools.js +46 -0
- package/src/mcp-profile-tools.js +46 -0
- package/src/mcp-rate-tools.js +42 -0
- package/src/mcp-register-tools.js +517 -0
- package/src/mcp-report-tools.js +101 -0
- package/src/mcp-role-tools.js +112 -0
- package/src/mcp-saved-positions-tools.js +55 -0
- package/src/mcp-server.js +170 -0
- package/src/mcp-show-project-tools.js +50 -0
- package/src/mcp-socials-tools.js +39 -0
- package/src/memory-structure-detector.js +108 -0
- package/src/model-call-record.js +198 -0
- package/src/onboarding-availability.js +26 -0
- package/src/onboarding-client.js +364 -0
- package/src/onboarding-flow.js +1078 -0
- package/src/onboarding-livekit-client.js +102 -0
- package/src/onboarding-status-client.js +42 -0
- package/src/open-file.js +32 -0
- package/src/osc-link.js +16 -0
- package/src/portfolio-client.js +164 -0
- package/src/portfolio-git-info.js +61 -0
- package/src/portfolios-client.js +85 -0
- package/src/portfolios-flow.js +79 -0
- package/src/profile-client.js +125 -0
- package/src/profile-flow.js +115 -0
- package/src/profile-switch.js +46 -0
- package/src/prompt-select.js +29 -0
- package/src/rate-client.js +82 -0
- package/src/rate-flow.js +137 -0
- package/src/render-ai-fluency.js +266 -0
- package/src/render-certification.js +177 -0
- package/src/render-html.js +140 -0
- package/src/render-report-text.js +27 -0
- package/src/render-sheet.js +261 -0
- package/src/render-terminal.js +109 -0
- package/src/render-usage-report-text.js +155 -0
- package/src/repo-context.js +215 -0
- package/src/report-gating.js +49 -0
- package/src/report-store.js +226 -0
- package/src/report-theme.js +177 -0
- package/src/report-view-client.js +50 -0
- package/src/reveal-output.js +29 -0
- package/src/roadmap-content.js +453 -0
- package/src/roadmap-personalization.js +132 -0
- package/src/roadmap-prompt.js +154 -0
- package/src/roles-client.js +114 -0
- package/src/roles-flow.js +192 -0
- package/src/sanitize-network-text.js +36 -0
- package/src/saved-positions-client.js +71 -0
- package/src/saved-positions-flow.js +50 -0
- package/src/scan-exclusions.js +50 -0
- package/src/scanner.js +612 -0
- package/src/scope-signals.js +148 -0
- package/src/secret-prompt.js +72 -0
- package/src/session-gate.js +30 -0
- package/src/session-refresh.js +51 -0
- package/src/session-scan.js +336 -0
- package/src/session-signals.js +36 -0
- package/src/shakers-wordmark.js +17 -0
- package/src/share-card.js +362 -0
- package/src/share-certification.js +111 -0
- package/src/share-consent-state.js +157 -0
- package/src/share-payload.js +300 -0
- package/src/share.js +184 -0
- package/src/show-project-client.js +58 -0
- package/src/show-project-flow.js +119 -0
- package/src/signup-client.js +91 -0
- package/src/skills-client.js +102 -0
- package/src/socials-client.js +91 -0
- package/src/socials-flow.js +83 -0
- package/src/specificity-extract.js +41 -0
- package/src/start-add-agents.js +306 -0
- package/src/start-add-portfolio.js +388 -0
- package/src/start-add-skills.js +260 -0
- package/src/stdin-ask.js +129 -0
- package/src/steering-extract.js +43 -0
- package/src/strip-internal-comments.js +45 -0
- package/src/tech-detector.js +295 -0
- package/src/templates/report-sheet.html +572 -0
- package/src/terminal-agents.js +199 -0
- package/src/terminal-format.js +85 -0
- package/src/terminal-progress.js +106 -0
- package/src/terminal-sections.js +219 -0
- package/src/tier-analysis.js +126 -0
- package/src/tier-engine.js +114 -0
- package/src/tier-projection.js +117 -0
- package/src/transcript-turns.js +49 -0
- package/src/translations-client.js +84 -0
- package/src/typewriter.js +154 -0
- package/src/usage-model-calls.js +119 -0
- package/src/usage-oneshot-commands.js +180 -0
- package/src/usage-repo-scope.js +162 -0
- package/src/usage-run-steps.js +338 -0
- package/src/work-streams.js +74 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { postJsonWithTimeout } = require('./backend-request');
|
|
4
|
+
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 20000;
|
|
6
|
+
|
|
7
|
+
function parseJson(raw) {
|
|
8
|
+
try {
|
|
9
|
+
return raw ? JSON.parse(raw) : null;
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function authHeaders({ accessToken } = {}) {
|
|
16
|
+
const headers = {};
|
|
17
|
+
if (typeof accessToken === 'string' && accessToken) headers.Authorization = `Bearer ${accessToken}`;
|
|
18
|
+
return headers;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function requestUsageReport({ accessToken } = {}, { endpoint, timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {
|
|
22
|
+
if (!endpoint) return { ok: false, reason: 'no-endpoint' };
|
|
23
|
+
|
|
24
|
+
let res;
|
|
25
|
+
try {
|
|
26
|
+
res = await postJsonWithTimeout(endpoint, null, timeoutMs, 'GET', null, authHeaders({ accessToken }));
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return { ok: false, reason: (e && e.kind) || 'network-error' };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (res.status < 200 || res.status >= 300) {
|
|
32
|
+
return { ok: false, reason: `http-${res.status}` };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const json = parseJson(res.raw);
|
|
36
|
+
const data = json && typeof json === 'object' ? json.data : null;
|
|
37
|
+
if (!data || typeof data !== 'object') return { ok: false, reason: 'bad-response' };
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
ok: true,
|
|
41
|
+
report: data.report && typeof data.report === 'object' ? data.report : null,
|
|
42
|
+
fluency: data.fluency && typeof data.fluency === 'object' ? data.fluency : null,
|
|
43
|
+
interactionQuality:
|
|
44
|
+
data.interactionQuality && typeof data.interactionQuality === 'object'
|
|
45
|
+
? data.interactionQuality
|
|
46
|
+
: null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = { requestUsageReport };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Shared, reusable output reveal for the NEW talent commands: buffer the human
|
|
4
|
+
// render and type it out with the report's typewriter pacing (bounded by
|
|
5
|
+
// `maxTotalMs`). ONE place, so every new command animates consistently.
|
|
6
|
+
//
|
|
7
|
+
// The LOADER stays live: on a TTY `io.withProgress` animates on stderr during the
|
|
8
|
+
// fetch; only the post-fetch RENDER is buffered here and revealed afterwards.
|
|
9
|
+
//
|
|
10
|
+
// GATE (reused from the typewriter, not reinvented): no animation in `--json`
|
|
11
|
+
// (machine output), in an interactive setter (live prompts), off a TTY, or under
|
|
12
|
+
// NO_ANIMATION — in those cases writes are passed straight through.
|
|
13
|
+
|
|
14
|
+
const { typeOut, revealEnabled } = require('./typewriter');
|
|
15
|
+
|
|
16
|
+
// Returns `{ write, finish }`. When animating, `write` buffers and `finish`
|
|
17
|
+
// types the buffer out; otherwise `write` passes through and `finish` is a no-op.
|
|
18
|
+
function makeRevealSink({ json = false, interactive = false, out = null, stream = process.stdout, env = process.env, sleep } = {}) {
|
|
19
|
+
const passthrough = out || ((s) => { if (stream && typeof stream.write === 'function') stream.write(s); });
|
|
20
|
+
const animating = !json && !interactive && !out && revealEnabled({ stream, env });
|
|
21
|
+
if (!animating) return { write: passthrough, finish: async () => {} };
|
|
22
|
+
let buf = '';
|
|
23
|
+
return {
|
|
24
|
+
write: (s) => { buf += s; },
|
|
25
|
+
finish: async () => { if (buf) await typeOut(buf, { stream, ...(sleep ? { sleep } : {}) }); },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = { makeRevealSink };
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Curated tier roadmap content (talents-ai-score, issue 020 / ADR-013/014).
|
|
4
|
+
|
|
5
|
+
const TIER_JUMPS_ES = {
|
|
6
|
+
T0: {
|
|
7
|
+
title: 'T0 → T1 · Banco vacío → Primera herramienta',
|
|
8
|
+
upgradeWhen: '`totalDetected >= 1` (una herramienta de IA detectada por existencia de fichero/dir/binario/extensión — `detectors.js`).',
|
|
9
|
+
unlocks: 'Tu primera herramienta de IA en el entorno de trabajo. Dejas de alternar con una pestaña de chat aparte: la IA vive donde escribes código y ve el fichero que tienes delante. Es el salto de "consulto a la IA" a "trabajo con la IA".',
|
|
10
|
+
steps: [
|
|
11
|
+
{ text: 'Elige una herramienta acorde a cómo trabajas — si vives en la terminal, una CLI agéntica (Claude Code, Codex CLI); si vives en el editor, un asistente de IDE (Copilot, Cursor).', estimate: '5 min' },
|
|
12
|
+
{ text: 'Instálala siguiendo la vía oficial de su proveedor.', estimate: '10-15 min' },
|
|
13
|
+
{ text: 'Ábrela en un proyecto real y pídele algo que ibas a hacer igualmente (explicar una función, escribir un test).', estimate: '10 min' },
|
|
14
|
+
],
|
|
15
|
+
snippet: {
|
|
16
|
+
language: 'bash',
|
|
17
|
+
label: 'instalación de una CLI agéntica (deja el binario `claude` en el PATH y `~/.claude`, dos de las señales de T1)',
|
|
18
|
+
filename: null,
|
|
19
|
+
code: '# Claude Code (CLI agéntica) — instalación oficial\nnpm install -g @anthropic-ai/claude-code\n# arráncala una vez en tu proyecto para que cree ~/.claude\nclaude',
|
|
20
|
+
},
|
|
21
|
+
tips: [
|
|
22
|
+
'Empieza por una herramienta, no cinco. El tier premia tenerla, pero tu soltura la da usar una a fondo, no coleccionarlas.',
|
|
23
|
+
'Pruébala en trabajo real desde el minuto uno; los tutoriales de juguete no enseñan dónde te ayuda de verdad.',
|
|
24
|
+
],
|
|
25
|
+
commonMistakes: [
|
|
26
|
+
'Usar una IA solo en el navegador (chat web) y nada en el entorno local → el CLI no deja rastro de eso y te mantiene en T0. La herramienta mide huella local, no lo que haces en una pestaña.',
|
|
27
|
+
'Instalar la extensión pero en un editor que el CLI no rastrea. Las señales de extensión miran ~/.vscode, ~/.vscode-insiders y ~/.cursor; una extensión en otro editor puede no contar.',
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
T1: {
|
|
32
|
+
title: 'T1 → T2 · Primera herramienta → Banco con notas',
|
|
33
|
+
upgradeWhen: '`context >= 1`, es decir ≥1 fichero de contexto persistente (`instructions + config + rules`: `CLAUDE.md`, `GEMINI.md`, `AGENTS.md`, `.github/copilot-instructions.md`, `.cursorrules`/`.cursor/rules/*.mdc`, `.windsurfrules`/`.windsurf/rules/*.md`, config de Aider/Continue).',
|
|
34
|
+
unlocks: 'Contexto que no tienes que reexplicar cada vez. Un fichero de instrucciones deja escrito cómo es tu proyecto (stack, convenciones, qué no tocar) y la IA lo lee en cada sesión. El salto de "le repito lo mismo cada mañana" a "ya sabe cómo trabajamos aquí".',
|
|
35
|
+
steps: [
|
|
36
|
+
{ text: 'Crea el fichero de instrucciones que corresponda a tu herramienta, en la raíz del proyecto.', estimate: '5 min' },
|
|
37
|
+
{ text: 'Escribe lo mínimo que repites siempre: qué es el proyecto, stack, 3-4 convenciones, qué está prohibido tocar.', estimate: '15-20 min' },
|
|
38
|
+
{ text: 'Prueba una tarea y ajusta el fichero cuando la IA se salte una convención.', estimate: '10 min' },
|
|
39
|
+
],
|
|
40
|
+
snippet: {
|
|
41
|
+
language: 'markdown',
|
|
42
|
+
label: 'CLAUDE.md en la raíz del proyecto (su mera existencia cuenta como instructions = 1 y te sube a T2)',
|
|
43
|
+
filename: 'CLAUDE.md',
|
|
44
|
+
code: '# <Nombre del proyecto>\n\n## Qué es\nUna frase sobre qué hace este proyecto y para quién.\n\n## Stack\n- Lenguaje / framework principal\n- Base de datos\n- Cómo se ejecutan los tests\n\n## Convenciones\n- Estilo de commits.\n- Cómo se nombran los ficheros.\n- Qué NO tocar sin avisar.',
|
|
45
|
+
},
|
|
46
|
+
tips: [
|
|
47
|
+
'Corto y vivo gana a largo y muerto. Un fichero de 20 líneas que actualizas vale más que uno de 200 que nadie mantiene.',
|
|
48
|
+
'Guárdalo en el repo: viaja con el equipo y no lo pierdes al cambiar de máquina.',
|
|
49
|
+
'Escribe las prohibiciones explícitas ("no toques las migraciones ya aplicadas"): es donde más se desvía la IA sin contexto.',
|
|
50
|
+
],
|
|
51
|
+
commonMistakes: [
|
|
52
|
+
'Poner las instrucciones en un README o en un fichero con nombre inventado → el CLI solo cuenta los nombres canónicos (CLAUDE.md, .cursorrules, etc.). Nombre equivocado, no sube de tier.',
|
|
53
|
+
'Crear el fichero vacío o solo con el título. Existe, sí, pero no te da lo que el tier promete: el valor está en el contenido, no en el fichero.',
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
T2: {
|
|
58
|
+
title: 'T2 → T3 · Banco con notas → Banco conectado',
|
|
59
|
+
upgradeWhen: '`mcpServers >= 1` (conteo de claves en `mcpServers` de `.mcp.json`, `~/.claude.json`, `.cursor/mcp.json`, `~/.codeium/windsurf/mcp_config.json`, `~/.gemini/settings.json` — `scanner.js::countJsonKeys`).',
|
|
60
|
+
unlocks: 'Conectar tu primer servidor MCP deja de darle a la IA solo tu código: le das acceso a tus datos y sistemas reales (tu base de datos, tu tracker de incidencias, tu documentación) sin copiar y pegar. El salto de "la IA lee mi proyecto" a "la IA consulta mis fuentes" es el que más tiempo ahorra en tareas repetitivas.',
|
|
61
|
+
steps: [
|
|
62
|
+
{ text: 'Elige una fuente que consultes a diario (tu BD de desarrollo, tu sistema de tickets, tu sistema de ficheros).', estimate: '5 min' },
|
|
63
|
+
{ text: 'Instala un servidor MCP para esa fuente y decláralo en tu config.', estimate: '15-20 min' },
|
|
64
|
+
{ text: 'Verifica que la herramienta lo carga (arranca la CLI/editor y comprueba que el servidor aparece disponible).', estimate: '5 min' },
|
|
65
|
+
{ text: 'Haz una consulta real que antes hacías a mano (ej. "resume los últimos 5 tickets abiertos").', estimate: '5 min' },
|
|
66
|
+
],
|
|
67
|
+
snippet: {
|
|
68
|
+
language: 'json',
|
|
69
|
+
label: '.mcp.json en la raíz del proyecto (el CLI cuenta las claves de mcpServers; con una ya subes a T3)',
|
|
70
|
+
filename: '.mcp.json',
|
|
71
|
+
code: '{\n "mcpServers": {\n "filesystem": {\n "command": "npx",\n "args": ["-y", "@modelcontextprotocol/server-filesystem", "./docs"]\n }\n }\n}',
|
|
72
|
+
},
|
|
73
|
+
tips: [
|
|
74
|
+
'Empieza por un MCP de solo lectura (filesystem, docs): el valor aparece rápido y el riesgo es mínimo.',
|
|
75
|
+
'Un MCP bien elegido rinde más que cinco a medias. El tier premia tenerlo conectado, pero tu productividad la mueve usarlo.',
|
|
76
|
+
'Guarda el .mcp.json en el repo del proyecto: así viaja con el equipo y no lo pierdes al cambiar de máquina.',
|
|
77
|
+
],
|
|
78
|
+
commonMistakes: [
|
|
79
|
+
'Configurar el MCP en un fichero que la herramienta no lee (ruta equivocada) → el servidor no arranca y el CLI no lo cuenta. Verifica siempre el paso 3.',
|
|
80
|
+
'Dejar el bloque mcpServers vacío ({}) — cuenta como 0 servidores, no sube de tier.',
|
|
81
|
+
'Pegar credenciales dentro del .mcp.json y subirlo al repo. Usa variables de entorno; nunca claves en claro (además, es justo el tipo de fuga que el AI Footprint evita capturar).',
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
T3: {
|
|
86
|
+
title: 'T3 → T4 · Banco conectado → Herramienta propia',
|
|
87
|
+
upgradeWhen: '`custom >= 1`, es decir ≥1 asset propio reutilizable (`skills + commands + rules`: dirs en `.claude/skills/`, ficheros `.claude/commands/*.md`, o reglas propias de Cursor/Windsurf).',
|
|
88
|
+
unlocks: 'Dejas de escribir el mismo prompt largo una y otra vez: lo conviertes en un asset reutilizable (un comando, una skill) que invocas por su nombre. El salto de "reescribo las instrucciones cada vez" a "tengo mis propias herramientas empaquetadas".',
|
|
89
|
+
steps: [
|
|
90
|
+
{ text: 'Identifica un prompt que repites (revisar un PR, generar un test, redactar un changelog).', estimate: '5 min' },
|
|
91
|
+
{ text: 'Empaquétalo como comando o skill en la carpeta que tu herramienta reconoce.', estimate: '15-25 min' },
|
|
92
|
+
{ text: 'Invócalo por su nombre en una tarea real y púlelo hasta que no tengas que corregirlo.', estimate: '10 min' },
|
|
93
|
+
],
|
|
94
|
+
snippet: {
|
|
95
|
+
language: 'markdown',
|
|
96
|
+
label: 'una skill propia en .claude/skills/review-diff/SKILL.md (cada subcarpeta de .claude/skills/ cuenta como skills += 1 y te sube a T4)',
|
|
97
|
+
filename: '.claude/skills/review-diff/SKILL.md',
|
|
98
|
+
code: '---\nname: review-diff\ndescription: Revisa el diff actual contra los estándares del proyecto\n---\n1. Muestra el diff frente a la rama base.\n2. Marca cualquier cosa que rompa las convenciones de CLAUDE.md.\n3. Señala tests que falten para el código nuevo.',
|
|
99
|
+
},
|
|
100
|
+
tips: [
|
|
101
|
+
'Empaqueta lo que ya haces cada día, no lo que crees que "deberías" automatizar. El uso real es la señal de qué merece ser un asset.',
|
|
102
|
+
'Nómbralos con verbos claros (review-diff, write-migration): un catálogo legible se usa; uno críptico se olvida.',
|
|
103
|
+
],
|
|
104
|
+
commonMistakes: [
|
|
105
|
+
'Meter la skill/comando en una carpeta con otro nombre → el CLI cuenta subdirectorios de .claude/skills/ y ficheros .md de .claude/commands/; fuera de ahí no cuenta.',
|
|
106
|
+
'Guardar el comando con extensión distinta de .md en commands/ → no entra en el conteo.',
|
|
107
|
+
'Crear diez comandos de una línea para "subir rápido": cuentan para el número, pero es justo el tipo de inflado que el dato asume como indicativo, no verificado. No te hace mejor; te hace medible.',
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
T4: {
|
|
112
|
+
title: 'T4 → T5 · Herramienta propia → Operador agéntico',
|
|
113
|
+
upgradeWhen: '`hasAgentic` y `mcp >= 1` y `custom >= 1`. `hasAgentic` = tener una CLI agéntica del conjunto AGENTIC_IDS (Claude Code, Aider, Gemini CLI, Codex CLI y Amazon Q, añadido por decisión cerrada #4).',
|
|
114
|
+
unlocks: 'T5 es el punto donde tu setup deja de asistirte paso a paso y empieza a ejecutar tareas de principio a fin: una CLI agéntica que, apoyada en tus MCP y en tus skills/comandos propios, encadena varios pasos sola. Es el salto de "me sugiere" a "lo hace y me lo trae para revisar".',
|
|
115
|
+
steps: [
|
|
116
|
+
{ text: 'Asegúrate de tener una CLI agéntica (Claude Code, Aider, Gemini CLI, Codex CLI o Amazon Q). Si trabajas solo en un editor con autocompletado, instala una.', estimate: '15 min' },
|
|
117
|
+
{ text: 'Confirma que ya cumples los prerrequisitos de T5: al menos 1 MCP (T3) y al menos 1 skill/comando/regla propia (T4). Si te falta alguno, el CLI te mantiene en T4.', estimate: '5 min' },
|
|
118
|
+
{ text: 'Crea un comando propio que orqueste una tarea recurrente completa (ej. "prepara el PR": lint + tests + resumen de cambios).', estimate: '30-45 min' },
|
|
119
|
+
{ text: 'Ejecútalo en un flujo real y ajusta hasta que necesites intervenir lo mínimo.', estimate: 'variable' },
|
|
120
|
+
],
|
|
121
|
+
snippet: {
|
|
122
|
+
language: 'markdown',
|
|
123
|
+
label: 'un comando propio en .claude/commands/prep-pr.md (el CLI cuenta los .md de commands/ como customización)',
|
|
124
|
+
filename: '.claude/commands/prep-pr.md',
|
|
125
|
+
code: '---\ndescription: Prepara una rama para PR — lint, tests y resumen de cambios\n---\n1. Ejecuta el linter y los tests del proyecto; si algo falla, párate y muéstramelo.\n2. Resume en 5 bullets los cambios frente a la rama base.\n3. Redacta un título de PR en Conventional Commits.',
|
|
126
|
+
},
|
|
127
|
+
tips: [
|
|
128
|
+
'El operador agéntico rinde cuando le das límites claros en el comando: qué puede tocar, cuándo parar, qué revisar contigo.',
|
|
129
|
+
'Reutiliza tus MCP dentro del comando (el que conectaste en T3): ahí es donde el agente pasa de "escribe código" a "consulta, decide y actúa".',
|
|
130
|
+
'Un comando que ejecutas cada día vale más que diez que escribiste una vez. Mide por uso, no por cantidad.',
|
|
131
|
+
],
|
|
132
|
+
commonMistakes: [
|
|
133
|
+
'Tener CLI agéntica y skills, pero ningún MCP → te quedas en T4: T5 exige las tres piezas a la vez.',
|
|
134
|
+
'Crear comandos que solo envuelven un prompt trivial de una línea: cuentan para el número, pero no te dan la orquestación real que el tier promete.',
|
|
135
|
+
'Dar al agente permiso total sin puntos de revisión: sube el tier, pero es la vía más rápida a un cambio que no querías. La ladder mide setup, no criterio — el criterio lo pones tú.',
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
T5: {
|
|
140
|
+
title: 'T5 → T6 · Operador agéntico → Multi-agente',
|
|
141
|
+
upgradeWhen: '`agentCounts.agents >= 2` (≥2 ficheros .claude/agents/*.md con frontmatter name válido — agent-org-chart.js::parseAgentOrgChart).',
|
|
142
|
+
unlocks: 'Dejas de tener un asistente todoterreno y pasas a un equipo de agentes especializados: uno para backend, otro para revisar, otro para tests. Cada uno con su rol y sus herramientas. El salto de "un ayudante que hace de todo" a "un equipo donde cada pieza sabe lo suyo".',
|
|
143
|
+
steps: [
|
|
144
|
+
{ text: 'Parte tu trabajo en 2-3 roles claros que hoy mezclas (ej. "escribir código" vs. "revisar").', estimate: '10 min' },
|
|
145
|
+
{ text: 'Crea un fichero de agente por rol en .claude/agents/, cada uno con su name, sus tools y su model.', estimate: '20-30 min' },
|
|
146
|
+
{ text: 'Úsalos en una tarea real delegando cada parte al agente que toca.', estimate: 'variable' },
|
|
147
|
+
],
|
|
148
|
+
snippet: {
|
|
149
|
+
language: 'markdown',
|
|
150
|
+
label: 'dos definiciones de agente (dos ficheros con name válido → agents = 2, te sube a T6). El CLI lee solo la estructura del frontmatter (name, tools, model), nunca el cuerpo ni la descripción',
|
|
151
|
+
filename: '.claude/agents/reviewer.md',
|
|
152
|
+
code: '---\nname: reviewer\ntools: Read, Grep\nmodel: sonnet\n---\nRevisa código contra las convenciones del proyecto. No modifica ficheros.',
|
|
153
|
+
secondFile: {
|
|
154
|
+
filename: '.claude/agents/tester.md',
|
|
155
|
+
code: '---\nname: tester\ntools: Read, Write, Bash\nmodel: sonnet\n---\nEscribe y ejecuta tests para el código nuevo.',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
tips: [
|
|
159
|
+
'Roles con fronteras nítidas rinden más que muchos agentes solapados. Dos bien definidos baten a cinco difusos.',
|
|
160
|
+
'Limita las tools de cada agente a lo que su rol necesita (un revisor no necesita escribir): además de más seguro, hace el organigrama legible.',
|
|
161
|
+
],
|
|
162
|
+
commonMistakes: [
|
|
163
|
+
'Escribir un agente sin la clave name en el frontmatter → el parser lo descarta y no cuenta. Necesitas name en cada fichero.',
|
|
164
|
+
'Dejar un solo agente (agents = 1): T6 exige dos o más. Un único agente es todavía T5.',
|
|
165
|
+
'Meter los ficheros fuera de .claude/agents/ → el parser está acotado a esa carpeta (en proyecto y en home, por el alcance proyecto ∪ home). Fuera de ahí no se ven.',
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
T6: {
|
|
170
|
+
title: 'T6 → T7 · Multi-agente → Taller orquestado',
|
|
171
|
+
upgradeWhen: '`hooks >= 1` (≥1 hook declarado en .claude/settings.json — scanner.js::countJsonKeys(settings.json, \'hooks\')).',
|
|
172
|
+
unlocks: 'Automatización que se dispara sola en los momentos clave: un hook ejecuta lint antes de cada commit, o bloquea un comando peligroso sin que tengas que acordarte. El salto de "delego tareas a mis agentes" a "mi taller reacciona solo a lo que pasa".',
|
|
173
|
+
steps: [
|
|
174
|
+
{ text: 'Elige un momento que quieras blindar (antes de commit, antes de ejecutar un comando, al terminar una tarea).', estimate: '5 min' },
|
|
175
|
+
{ text: 'Declara un hook para ese evento en .claude/settings.json.', estimate: '15-25 min' },
|
|
176
|
+
{ text: 'Provoca el evento y confirma que el hook se dispara como esperabas.', estimate: '10 min' },
|
|
177
|
+
],
|
|
178
|
+
snippet: {
|
|
179
|
+
language: 'json',
|
|
180
|
+
label: '.claude/settings.json con un hook (la clave hooks con ≥1 entrada te sube a T7)',
|
|
181
|
+
filename: '.claude/settings.json',
|
|
182
|
+
code: '{\n "hooks": {\n "PreToolUse": [\n {\n "matcher": "Bash",\n "hooks": [\n { "type": "command", "command": "echo \'Revisa el comando antes de ejecutarlo\'" }\n ]\n }\n ]\n }\n}',
|
|
183
|
+
},
|
|
184
|
+
tips: [
|
|
185
|
+
'Empieza por un hook defensivo (avisar o bloquear), no destructivo: aprendes el mecanismo sin riesgo.',
|
|
186
|
+
'Un hook que se dispara siempre y estorba lo acabas desactivando. Acótalo con matcher a los casos que de verdad importan.',
|
|
187
|
+
],
|
|
188
|
+
commonMistakes: [
|
|
189
|
+
'Escribir la automatización como un script suelto en el repo en vez de declararla en settings.json → hoy el CLI cuenta hooks por la clave hooks del settings.json; un script suelto no es una categoría detectada todavía y no sube de tier.',
|
|
190
|
+
'Dejar la clave hooks presente pero vacía → cuenta como 0, no sube.',
|
|
191
|
+
'Un JSON con error de sintaxis en settings.json → el conteo devuelve 0 (el parser falla en silencio). Valida el JSON.',
|
|
192
|
+
],
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// T7 has no "next tier" — a distinct terminal shape (source doc: "Sin pasos
|
|
197
|
+
// de subida. No hay tier superior").
|
|
198
|
+
const T7_TERMINAL_ES = {
|
|
199
|
+
title: 'T7 · Taller orquestado — nivel máximo',
|
|
200
|
+
intro: 'Ya estás en el tier más alto de la escala. Tu setup combina multi-agente + MCP + assets propios + automatización por hooks: está equipado de arriba a abajo.',
|
|
201
|
+
whatRemains: 'El tier ya no sube, pero el equipamiento no es el trabajo. A partir de aquí el margen está en usar lo que tienes, no en instalar más: documentar tu setup para que otros lo repliquen, podar lo que no usas, y afilar cada agente/comando con el trabajo real. La escala mide cómo tienes montado el banco; que salgan buenas piezas de él depende de ti.',
|
|
202
|
+
consolidationSteps: [
|
|
203
|
+
'Afina tus hooks y agentes con el trabajo real: recorta lo que estorba, acota los matchers y ajusta las tools/límites de cada agente a su rol.',
|
|
204
|
+
'Poda lo que no usas: revisa qué assets llevas tiempo sin tocar (el CLI expone recency/mtime de forma informativa, no como gate — ADR-003) y elimina lo redundante.',
|
|
205
|
+
'Mantén vivos tus ficheros de contexto (CLAUDE.md, reglas, comandos): actualízalos cuando cambien el stack o las convenciones, o dejan de ayudar.',
|
|
206
|
+
'Empaqueta y contribuye tus skills/comandos a un repo compartido del equipo para que tu setup escale más allá de tu máquina.',
|
|
207
|
+
'Documenta tu organigrama de agentes y compártelo como referencia interna para que otros lo repliquen.',
|
|
208
|
+
'Mide el impacto real (tiempo ahorrado, tareas delegadas de principio a fin) y usa ese dato para decidir qué merece seguir en tu banco.',
|
|
209
|
+
],
|
|
210
|
+
honestyNote: 'Estar en T7 significa que tienes el banco de trabajo mejor equipado que el CLI sabe medir. No significa que seas quien mejor usa la IA: el dato es una proxy de setup, indicativa y no verificada (ADR-007). No se lee como "calidad IA del Talent".',
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const TIER_JUMPS_EN = {
|
|
214
|
+
T0: {
|
|
215
|
+
title: 'T0 → T1 · Empty bench → First tool',
|
|
216
|
+
upgradeWhen: '`totalDetected >= 1` (one AI tool detected by existence of a file/dir/binary/extension — `detectors.js`).',
|
|
217
|
+
unlocks: 'Your first AI tool inside your work environment. You stop juggling a separate chat tab: the AI lives where you write code and sees the file in front of you. The jump from "I ask the AI" to "I work with the AI".',
|
|
218
|
+
steps: [
|
|
219
|
+
{ text: 'Pick a tool that fits how you work — if you live in the terminal, an agentic CLI (Claude Code, Codex CLI); if you live in the editor, an IDE assistant (Copilot, Cursor).', estimate: '5 min' },
|
|
220
|
+
{ text: "Install it following your vendor's official path.", estimate: '10-15 min' },
|
|
221
|
+
{ text: 'Open it in a real project and ask for something you were going to do anyway (explain a function, write a test).', estimate: '10 min' },
|
|
222
|
+
],
|
|
223
|
+
snippet: {
|
|
224
|
+
language: 'bash',
|
|
225
|
+
label: 'installing an agentic CLI (drops the `claude` binary on your PATH and creates `~/.claude`, two of the T1 signals)',
|
|
226
|
+
filename: null,
|
|
227
|
+
code: '# Claude Code (agentic CLI) — official install\nnpm install -g @anthropic-ai/claude-code\n# run it once in your project so it creates ~/.claude\nclaude',
|
|
228
|
+
},
|
|
229
|
+
tips: [
|
|
230
|
+
'Start with one tool, not five. The tier rewards having it, but your fluency comes from using one deeply, not from collecting them.',
|
|
231
|
+
"Try it on real work from day one; toy tutorials won't show you where it actually helps.",
|
|
232
|
+
],
|
|
233
|
+
commonMistakes: [
|
|
234
|
+
'Using AI only in the browser (web chat) and nothing locally → the CLI leaves no trace of that and keeps you at T0. The tool measures the local footprint, not what you do in a tab.',
|
|
235
|
+
"Installing the extension but in an editor the CLI doesn't scan. Extension signals look at ~/.vscode, ~/.vscode-insiders and ~/.cursor; an extension in another editor may not count.",
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
T1: {
|
|
240
|
+
title: 'T1 → T2 · First tool → Bench with notes',
|
|
241
|
+
upgradeWhen: '`context >= 1`, i.e. ≥1 persistent context file (`instructions + config + rules`: `CLAUDE.md`, `GEMINI.md`, `AGENTS.md`, `.github/copilot-instructions.md`, `.cursorrules`/`.cursor/rules/*.mdc`, `.windsurfrules`/`.windsurf/rules/*.md`, Aider/Continue config).',
|
|
242
|
+
unlocks: 'Context you don\'t have to re-explain every time. An instructions file writes down what your project is (stack, conventions, what not to touch) and the AI reads it every session. The jump from "I repeat the same thing every morning" to "it already knows how we work here".',
|
|
243
|
+
steps: [
|
|
244
|
+
{ text: 'Create the instructions file that matches your tool, at the project root.', estimate: '5 min' },
|
|
245
|
+
{ text: "Write the minimum you always repeat: what the project is, stack, 3-4 conventions, what's off-limits.", estimate: '15-20 min' },
|
|
246
|
+
{ text: 'Run a task and refine the file whenever the AI skips a convention.', estimate: '10 min' },
|
|
247
|
+
],
|
|
248
|
+
snippet: {
|
|
249
|
+
language: 'markdown',
|
|
250
|
+
label: '`CLAUDE.md` at the project root (its mere existence counts as instructions = 1 and moves you to T2)',
|
|
251
|
+
filename: 'CLAUDE.md',
|
|
252
|
+
code: '# <Project name>\n\n## What it is\nOne sentence on what this project does and for whom.\n\n## Stack\n- Main language / framework\n- Database\n- How tests are run\n\n## Conventions\n- Commit style.\n- How files are named.\n- What NOT to touch without asking.',
|
|
253
|
+
},
|
|
254
|
+
tips: [
|
|
255
|
+
'Short and alive beats long and dead. A 20-line file you keep updated is worth more than a 200-line one nobody maintains.',
|
|
256
|
+
"Keep it in the repo: it travels with the team and you won't lose it when you switch machines.",
|
|
257
|
+
'Write the explicit prohibitions ("don\'t touch already-applied migrations"): that\'s where the AI drifts most without context.',
|
|
258
|
+
],
|
|
259
|
+
commonMistakes: [
|
|
260
|
+
'Putting the instructions in a README or a made-up filename → the CLI only counts the canonical names (CLAUDE.md, .cursorrules, etc.). Wrong name, no level-up.',
|
|
261
|
+
"Creating the file empty or with just the title. It exists, sure, but it doesn't give you what the tier promises: the value is in the content, not the file.",
|
|
262
|
+
],
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
T2: {
|
|
266
|
+
title: 'T2 → T3 · Bench with notes → Connected bench',
|
|
267
|
+
upgradeWhen: '`mcpServers >= 1` (count of keys under `mcpServers` in `.mcp.json`, `~/.claude.json`, `.cursor/mcp.json`, `~/.codeium/windsurf/mcp_config.json`, `~/.gemini/settings.json` — `scanner.js::countJsonKeys`).',
|
|
268
|
+
unlocks: 'Connecting your first MCP server stops giving the AI only your code: you give it access to your real data and systems (your database, your issue tracker, your docs) without copy-pasting. The jump from "the AI reads my project" to "the AI queries my sources" is the one that saves the most time on repetitive tasks.',
|
|
269
|
+
steps: [
|
|
270
|
+
{ text: 'Pick a source you consult daily (your dev database, your ticketing system, your file system).', estimate: '5 min' },
|
|
271
|
+
{ text: 'Install an MCP server for that source and declare it in your config.', estimate: '15-20 min' },
|
|
272
|
+
{ text: 'Verify the tool loads it (start the CLI/editor and check the server shows up as available).', estimate: '5 min' },
|
|
273
|
+
{ text: 'Run a real query you used to do by hand (e.g. "summarize the last 5 open tickets").', estimate: '5 min' },
|
|
274
|
+
],
|
|
275
|
+
snippet: {
|
|
276
|
+
language: 'json',
|
|
277
|
+
label: '`.mcp.json` at the project root (the CLI counts the keys under mcpServers; one already moves you to T3)',
|
|
278
|
+
filename: '.mcp.json',
|
|
279
|
+
code: '{\n "mcpServers": {\n "filesystem": {\n "command": "npx",\n "args": ["-y", "@modelcontextprotocol/server-filesystem", "./docs"]\n }\n }\n}',
|
|
280
|
+
},
|
|
281
|
+
tips: [
|
|
282
|
+
'Start with a read-only MCP (filesystem, docs): the value shows up fast and the risk is minimal.',
|
|
283
|
+
'One well-chosen MCP pays off more than five half-baked ones. The tier rewards having it connected, but your productivity comes from using it.',
|
|
284
|
+
"Keep the .mcp.json in the project repo: it travels with the team and you won't lose it when you switch machines.",
|
|
285
|
+
],
|
|
286
|
+
commonMistakes: [
|
|
287
|
+
"Configuring the MCP in a file the tool doesn't read (wrong path) → the server won't start and the CLI won't count it. Always verify step 3.",
|
|
288
|
+
'Leaving the mcpServers block empty ({}) — counts as 0 servers, no level-up.',
|
|
289
|
+
"Pasting credentials inside .mcp.json and committing it. Use environment variables; never plaintext keys (that's exactly the kind of leak the AI Footprint avoids capturing).",
|
|
290
|
+
],
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
T3: {
|
|
294
|
+
title: 'T3 → T4 · Connected bench → Your own tooling',
|
|
295
|
+
upgradeWhen: '`custom >= 1`, i.e. ≥1 reusable asset of your own (`skills + commands + rules`: dirs under `.claude/skills/`, `.claude/commands/*.md` files, or your own Cursor/Windsurf rules).',
|
|
296
|
+
unlocks: 'You stop writing the same long prompt over and over: you turn it into a reusable asset (a command, a skill) you invoke by name. The jump from "I rewrite the instructions every time" to "I have my own packaged tools".',
|
|
297
|
+
steps: [
|
|
298
|
+
{ text: 'Identify a prompt you repeat (review a PR, generate a test, write a changelog).', estimate: '5 min' },
|
|
299
|
+
{ text: 'Package it as a command or skill in the folder your tool recognizes.', estimate: '15-25 min' },
|
|
300
|
+
{ text: "Invoke it by name on a real task and polish it until you don't have to correct it.", estimate: '10 min' },
|
|
301
|
+
],
|
|
302
|
+
snippet: {
|
|
303
|
+
language: 'markdown',
|
|
304
|
+
label: 'a skill of your own at .claude/skills/review-diff/SKILL.md (each subfolder of .claude/skills/ counts as skills += 1 and moves you to T4)',
|
|
305
|
+
filename: '.claude/skills/review-diff/SKILL.md',
|
|
306
|
+
code: '---\nname: review-diff\ndescription: Review the current diff against the project\'s standards\n---\n1. Show the diff against the base branch.\n2. Flag anything that breaks the conventions in CLAUDE.md.\n3. Point out tests missing for the new code.',
|
|
307
|
+
},
|
|
308
|
+
tips: [
|
|
309
|
+
'Package what you already do every day, not what you think you "should" automate. Real usage is the signal for what deserves to be an asset.',
|
|
310
|
+
'Name them with clear verbs (review-diff, write-migration): a readable catalog gets used; a cryptic one gets forgotten.',
|
|
311
|
+
],
|
|
312
|
+
commonMistakes: [
|
|
313
|
+
'Putting the skill/command in a folder with another name → the CLI counts subdirectories of .claude/skills/ and .md files in .claude/commands/; outside those, nothing counts.',
|
|
314
|
+
"Saving the command with an extension other than .md in commands/ → it won't enter the count.",
|
|
315
|
+
'Creating ten one-line commands just to "level up fast": they count toward the number, but that\'s exactly the kind of padding the data assumes as indicative, not verified. It doesn\'t make you better; it makes you measurable.',
|
|
316
|
+
],
|
|
317
|
+
},
|
|
318
|
+
|
|
319
|
+
T4: {
|
|
320
|
+
title: 'T4 → T5 · Your own tooling → Agentic operator',
|
|
321
|
+
upgradeWhen: '`hasAgentic` and `mcp >= 1` and `custom >= 1`. `hasAgentic` = having an agentic CLI from the AGENTIC_IDS set (Claude Code, Aider, Gemini CLI, Codex CLI and Amazon Q, added by closed decision #4).',
|
|
322
|
+
unlocks: 'T5 is where your setup stops assisting you step by step and starts running tasks end to end: an agentic CLI that, backed by your MCPs and your own skills/commands, chains several steps on its own. The jump from "it suggests" to "it does it and brings it back for me to review".',
|
|
323
|
+
steps: [
|
|
324
|
+
{ text: 'Make sure you have an agentic CLI (Claude Code, Aider, Gemini CLI, Codex CLI or Amazon Q). If you only work in an editor with autocomplete, install one.', estimate: '15 min' },
|
|
325
|
+
{ text: 'Confirm you already meet the T5 prerequisites: at least 1 MCP (T3) and at least 1 skill/command/rule of your own (T4). If either is missing, the CLI keeps you at T4.', estimate: '5 min' },
|
|
326
|
+
{ text: 'Create a command of your own that orchestrates a full recurring task (e.g. "prep the PR": lint + tests + change summary).', estimate: '30-45 min' },
|
|
327
|
+
{ text: 'Run it on a real flow and tune it until you need to step in as little as possible.', estimate: 'variable' },
|
|
328
|
+
],
|
|
329
|
+
snippet: {
|
|
330
|
+
language: 'markdown',
|
|
331
|
+
label: 'a command of your own at .claude/commands/prep-pr.md (the CLI counts the .md files in commands/ as customization)',
|
|
332
|
+
filename: '.claude/commands/prep-pr.md',
|
|
333
|
+
code: '---\ndescription: Prepare a branch for PR — lint, tests and change summary\n---\n1. Run the project\'s linter and tests; if anything fails, stop and show it to me.\n2. Summarize the changes against the base branch in 5 bullets.\n3. Draft a PR title in Conventional Commits.',
|
|
334
|
+
},
|
|
335
|
+
tips: [
|
|
336
|
+
'The agentic operator pays off when you give it clear limits in the command: what it may touch, when to stop, what to review with you.',
|
|
337
|
+
'Reuse your MCPs inside the command (the one you connected at T3): that\'s where the agent goes from "writes code" to "queries, decides and acts".',
|
|
338
|
+
'A command you run every day is worth more than ten you wrote once. Measure by usage, not by count.',
|
|
339
|
+
],
|
|
340
|
+
commonMistakes: [
|
|
341
|
+
'Having an agentic CLI and skills, but no MCP → you stay at T4: T5 requires all three pieces at once.',
|
|
342
|
+
"Creating commands that just wrap a trivial one-line prompt: they count toward the number, but they don't give you the real orchestration the tier promises.",
|
|
343
|
+
"Giving the agent full permissions with no review points: it raises the tier, but it's the fastest path to a change you didn't want. The ladder measures setup, not judgment — the judgment is yours.",
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
T5: {
|
|
348
|
+
title: 'T5 → T6 · Agentic operator → Multi-agent',
|
|
349
|
+
upgradeWhen: '`agentCounts.agents >= 2` (≥2 `.claude/agents/*.md` files with valid `name` frontmatter — `agent-org-chart.js::parseAgentOrgChart`).',
|
|
350
|
+
unlocks: 'You stop having one all-purpose assistant and move to a team of specialized agents: one for backend, one for reviewing, one for tests. Each with its role and its tools. The jump from "a helper that does everything" to "a team where each piece knows its own job".',
|
|
351
|
+
steps: [
|
|
352
|
+
{ text: 'Split your work into 2-3 clear roles you mix today (e.g. "write code" vs. "review").', estimate: '10 min' },
|
|
353
|
+
{ text: 'Create one agent file per role in .claude/agents/, each with its name, its tools and its model.', estimate: '20-30 min' },
|
|
354
|
+
{ text: 'Use them on a real task delegating each part to the right agent.', estimate: 'variable' },
|
|
355
|
+
],
|
|
356
|
+
snippet: {
|
|
357
|
+
language: 'markdown',
|
|
358
|
+
label: 'two agent definitions (two files with a valid name → agents = 2, moves you to T6). The CLI reads only the frontmatter structure (name, tools, model), never the body or the description',
|
|
359
|
+
filename: '.claude/agents/reviewer.md',
|
|
360
|
+
code: '---\nname: reviewer\ntools: Read, Grep\nmodel: sonnet\n---\nReviews code against the project\'s conventions. Does not modify files.',
|
|
361
|
+
secondFile: {
|
|
362
|
+
filename: '.claude/agents/tester.md',
|
|
363
|
+
code: '---\nname: tester\ntools: Read, Write, Bash\nmodel: sonnet\n---\nWrites and runs tests for new code.',
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
tips: [
|
|
367
|
+
'Roles with sharp boundaries pay off more than many overlapping agents. Two well-defined beat five fuzzy ones.',
|
|
368
|
+
"Limit each agent's tools to what its role needs (a reviewer doesn't need to write): besides being safer, it keeps the org chart readable.",
|
|
369
|
+
],
|
|
370
|
+
commonMistakes: [
|
|
371
|
+
"Writing an agent without the name key in the frontmatter → the parser discards it and it doesn't count. You need name in every file.",
|
|
372
|
+
'Leaving a single agent (agents = 1): T6 requires two or more. A single agent is still T5.',
|
|
373
|
+
"Placing the files outside .claude/agents/ → the parser is scoped to that folder (in project and in home, per the project ∪ home scope). Anywhere else, they're invisible.",
|
|
374
|
+
],
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
T6: {
|
|
378
|
+
title: 'T6 → T7 · Multi-agent → Orchestrated workshop',
|
|
379
|
+
upgradeWhen: "`hooks >= 1` (≥1 hook declared in `.claude/settings.json` — `scanner.js::countJsonKeys(settings.json, 'hooks')`).",
|
|
380
|
+
unlocks: 'Automation that fires on its own at the key moments: a hook runs lint before every commit, or blocks a dangerous command without you having to remember. The jump from "I delegate tasks to my agents" to "my workshop reacts on its own to what happens".',
|
|
381
|
+
steps: [
|
|
382
|
+
{ text: 'Pick a moment you want to harden (before commit, before running a command, when a task finishes).', estimate: '5 min' },
|
|
383
|
+
{ text: 'Declare a hook for that event in .claude/settings.json.', estimate: '15-25 min' },
|
|
384
|
+
{ text: 'Trigger the event and confirm the hook fires as you expected.', estimate: '10 min' },
|
|
385
|
+
],
|
|
386
|
+
snippet: {
|
|
387
|
+
language: 'json',
|
|
388
|
+
label: '.claude/settings.json with a hook (the hooks key with ≥1 entry moves you to T7)',
|
|
389
|
+
filename: '.claude/settings.json',
|
|
390
|
+
code: '{\n "hooks": {\n "PreToolUse": [\n {\n "matcher": "Bash",\n "hooks": [\n { "type": "command", "command": "echo \'Review the command before running it\'" }\n ]\n }\n ]\n }\n}',
|
|
391
|
+
},
|
|
392
|
+
tips: [
|
|
393
|
+
"Start with a defensive hook (warn or block), not destructive: you learn the mechanism without risk.",
|
|
394
|
+
'A hook that fires always and gets in the way ends up disabled. Scope it with matcher to the cases that actually matter.',
|
|
395
|
+
],
|
|
396
|
+
commonMistakes: [
|
|
397
|
+
'Writing the automation as a loose script in the repo instead of declaring it in settings.json → today the CLI counts hooks via the hooks key of settings.json; a loose script is not a detected category yet and won\'t level you up.',
|
|
398
|
+
'Leaving the hooks key present but empty → counts as 0, no level-up.',
|
|
399
|
+
'A JSON with a syntax error in settings.json → the count returns 0 (the parser fails silently). Validate the JSON.',
|
|
400
|
+
],
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// T7 has no "next tier" — a distinct terminal shape (source doc: "No
|
|
405
|
+
// level-up steps. There's no higher tier.").
|
|
406
|
+
const T7_TERMINAL_EN = {
|
|
407
|
+
title: 'T7 · Orchestrated workshop — top level',
|
|
408
|
+
intro: "You're at the top tier of the ladder. Your setup combines multi-agent + MCP + your own assets + hook-based automation: it's equipped top to bottom.",
|
|
409
|
+
whatRemains: "The tier no longer rises, but equipment isn't the work. From here the margin is in using what you have, not installing more: documenting your setup so others can replicate it, pruning what you don't use, and sharpening each agent/command with real work. The ladder measures how your bench is set up; whether good pieces come out of it is up to you.",
|
|
410
|
+
consolidationSteps: [
|
|
411
|
+
"Sharpen your hooks and agents against real work: trim what gets in the way, scope the matchers, and tune each agent's tools/limits to its role.",
|
|
412
|
+
"Prune what you don't use: review which assets you haven't touched in a while (the CLI exposes recency/mtime informatively, not as a gate — ADR-003) and drop the redundant ones.",
|
|
413
|
+
'Keep your context files (CLAUDE.md, rules, commands) alive: update them when the stack or conventions change, or they stop helping.',
|
|
414
|
+
'Package and contribute your skills/commands to a shared team repo so your setup scales beyond your own machine.',
|
|
415
|
+
'Document your agent org chart and share it as an internal reference so others can replicate it.',
|
|
416
|
+
'Measure the real impact (time saved, tasks delegated end to end) and use that to decide what deserves to stay on your bench.',
|
|
417
|
+
],
|
|
418
|
+
honestyNote: 'Being at T7 means you have the best-equipped bench the CLI knows how to measure. It does not mean you\'re the one who uses AI best: the data is a proxy for setup, indicative and unverified (ADR-007). It\'s not read as "the Talent\'s AI quality".',
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const CONTENT_BY_LANG = {
|
|
422
|
+
es: { jumps: TIER_JUMPS_ES, terminal: T7_TERMINAL_ES },
|
|
423
|
+
en: { jumps: TIER_JUMPS_EN, terminal: T7_TERMINAL_EN },
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// Returns the roadmap entry for the CURRENT tier only (never the whole ladder), or `null` for a genuinely unrecognized tier key (in ANY language).
|
|
427
|
+
function getRoadmapEntry(tierKey, lang = 'es') {
|
|
428
|
+
const requested = lang === 'en' ? 'en' : 'es';
|
|
429
|
+
|
|
430
|
+
if (tierKey === 'T7') {
|
|
431
|
+
const terminalContent = CONTENT_BY_LANG[requested].terminal;
|
|
432
|
+
if (terminalContent) {
|
|
433
|
+
return { tierKey: 'T7', maxTier: true, lang: requested, ...terminalContent };
|
|
434
|
+
}
|
|
435
|
+
return { tierKey: 'T7', maxTier: true, lang: requested, contentUnavailable: true };
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const esJump = TIER_JUMPS_ES[tierKey];
|
|
439
|
+
if (!esJump) return null; // genuinely unrecognized tier key, in any language
|
|
440
|
+
|
|
441
|
+
const jump = CONTENT_BY_LANG[requested].jumps[tierKey];
|
|
442
|
+
if (jump) return { tierKey, maxTier: false, lang: requested, ...jump };
|
|
443
|
+
|
|
444
|
+
return { tierKey, maxTier: false, lang: requested, contentUnavailable: true };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
module.exports = {
|
|
448
|
+
getRoadmapEntry,
|
|
449
|
+
TIER_JUMPS_ES,
|
|
450
|
+
T7_TERMINAL_ES,
|
|
451
|
+
TIER_JUMPS_EN,
|
|
452
|
+
T7_TERMINAL_EN,
|
|
453
|
+
};
|