openprompt-lang 0.10.0 → 0.11.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.
Files changed (42) hide show
  1. package/bin/cli.js +40 -19
  2. package/bin/create.js +56 -56
  3. package/bin/lint.js +13 -13
  4. package/docs/AI_CONTEXT.md +28 -10
  5. package/docs/FRAMEWORK.md +184 -18
  6. package/docs/flows/autenticacion-mpfr52fu.md +28 -0
  7. package/package.json +1 -1
  8. package/src/ai/prompt-builder.js +2 -2
  9. package/src/annotations/tags.json +2 -1
  10. package/src/cli/commands-context.js +27 -19
  11. package/src/cli/commands-init.js +7 -1
  12. package/src/cli/commands-opl.js +260 -0
  13. package/src/commands/context.js +1 -1
  14. package/src/commands/knowledge-helpers.js +84 -0
  15. package/src/commands/knowledge-query.js +2 -2
  16. package/src/commands/opl-assess.js +520 -0
  17. package/src/commands/opl-context-build.js +136 -0
  18. package/src/commands/opl-context-index.js +362 -0
  19. package/src/commands/opl-context.js +286 -0
  20. package/src/commands/opl-contracts.js +182 -0
  21. package/src/commands/opl-doc-flow.js +215 -0
  22. package/src/commands/opl-graph.js +206 -0
  23. package/src/commands/opl-help.js +79 -0
  24. package/src/commands/opl-index.js +254 -0
  25. package/src/commands/opl-init-knowledge.js +209 -0
  26. package/src/commands/opl-read.js +249 -0
  27. package/src/commands/opl-search.js +253 -0
  28. package/src/commands/opl-session.js +395 -0
  29. package/src/commands/opl-system.js +266 -0
  30. package/src/commands/opl-tutorial.js +226 -0
  31. package/src/commands/opl-upgrade.js +193 -0
  32. package/src/commands/pattern.js +2 -2
  33. package/src/commands/validate.js +46 -11
  34. package/src/mcp-server.js +2 -2
  35. package/src/mcp-workflow.js +1 -1
  36. package/src/templates/knowledge-repo/processed/index/index.json +783 -1
  37. package/src/templates/knowledge-repo/taxonomy/domains.json +257 -30
  38. package/src/templates/knowledge-repo/taxonomy/production-readiness.json +393 -0
  39. package/src/templates/knowledge-repo/taxonomy/systems.json +506 -0
  40. package/src/utils/annotations.js +43 -1
  41. package/src/utils/generate-framework-md.js +176 -16
  42. package/src/utils/knowledge-search.js +2 -2
package/bin/cli.js CHANGED
@@ -2,33 +2,54 @@
2
2
  // @use(commander, kind, contract, limit)
3
3
  // @kind(util)
4
4
  // @contract(in: argv -> out: void, sideEffect: ejecuta CLI)
5
- // @limit(lines: 60)
6
-
7
- import { Command } from 'commander'
8
- import chalk from 'chalk'
9
- import { readFileSync } from 'fs'
10
- import { join, dirname } from 'path'
11
- import { fileURLToPath } from 'url'
12
-
13
- import { register as registerInit } from '../src/cli/commands-init.js'
14
- import { register as registerContext } from '../src/cli/commands-context.js'
15
- import { register as registerAi } from '../src/cli/commands-ai.js'
16
- import { register as registerLang } from '../src/cli/commands-lang.js'
17
- import { register as registerKnowledge } from '../src/cli/commands-knowledge.js'
18
- import { register as registerWork } from '../src/cli/commands-work.js'
19
- import { register as registerLearning } from '../src/cli/commands-learning.js'
20
- import { register as registerMisc } from '../src/cli/commands-misc.js'
5
+ // @limit(lines: 90)
6
+
7
+ import { Command } from "commander"
8
+ import chalk from "chalk"
9
+ import { readFileSync } from "fs"
10
+ import { join, dirname } from "path"
11
+ import { fileURLToPath } from "url"
12
+
13
+ import { register as registerInit } from "../src/cli/commands-init.js"
14
+ import { register as registerContext } from "../src/cli/commands-context.js"
15
+ import { register as registerAi } from "../src/cli/commands-ai.js"
16
+ import { register as registerLang } from "../src/cli/commands-lang.js"
17
+ import { register as registerKnowledge } from "../src/cli/commands-knowledge.js"
18
+ import { register as registerWork } from "../src/cli/commands-work.js"
19
+ import { register as registerLearning } from "../src/cli/commands-learning.js"
20
+ import { register as registerOpl } from "../src/cli/commands-opl.js"
21
+ import { register as registerMisc } from "../src/cli/commands-misc.js"
21
22
 
22
23
  const __dirname = dirname(fileURLToPath(import.meta.url))
23
- const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'))
24
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"))
25
+
26
+ // ──────────────────────────────────────────────
27
+ // Si no hay argumentos o solo --help/-h, mostrar bienvenida OPL
28
+ // ──────────────────────────────────────────────
29
+ const args = process.argv.slice(2)
30
+ const isHelpOnly = args.length === 1 && (args[0] === "--help" || args[0] === "-h")
31
+ const hasNoArgs = args.length === 0
32
+
33
+ if (hasNoArgs || isHelpOnly) {
34
+ const { showWelcome } = await import("../src/commands/opl-help.js")
35
+ await showWelcome()
36
+ process.exit(0)
37
+ }
24
38
 
25
39
  const program = new Command()
26
40
 
41
+ // Override: --help muestra la welcome screen, no la lista de Commander
42
+ program.helpInformation = () => ""
43
+
27
44
  program
28
- .name('openPrompt-Lang')
29
- .description(chalk.cyan('Context Engine de anotaciones para desarrollo asistido por IA'))
45
+ .name("openPrompt-Lang")
46
+ .description(chalk.cyan("Context Engine de anotaciones para desarrollo asistido por IA"))
30
47
  .version(pkg.version)
31
48
 
49
+ // Registrar comandos OPL (puerta de entrada: help, tutorial, index, read)
50
+ registerOpl(program)
51
+
52
+ // Registrar comandos existentes
32
53
  registerInit(program)
33
54
  registerContext(program)
34
55
  registerAi(program)
package/bin/create.js CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { execSync } from 'child_process'
4
- import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, rmSync } from 'fs'
5
- import { join, dirname } from 'path'
6
- import { fileURLToPath } from 'url'
7
- import chalk from 'chalk'
3
+ import { execSync } from "child_process"
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, rmSync } from "fs"
5
+ import { join, dirname } from "path"
6
+ import { fileURLToPath } from "url"
7
+ import chalk from "chalk"
8
8
 
9
9
  const __dirname = dirname(fileURLToPath(import.meta.url))
10
10
 
11
- async function main () {
11
+ async function main() {
12
12
  const args = process.argv.slice(2)
13
- const projectName = args[0] || 'mi-app'
14
- const depsIndex = args.indexOf('--deps')
15
- const deps = depsIndex !== -1 ? args[depsIndex + 1]?.split(',') || [] : []
16
- const deployIndex = args.indexOf('--deploy')
13
+ const projectName = args[0] || "mi-app"
14
+ const depsIndex = args.indexOf("--deps")
15
+ const deps = depsIndex !== -1 ? args[depsIndex + 1]?.split(",") || [] : []
16
+ const deployIndex = args.indexOf("--deploy")
17
17
  const deploy = deployIndex !== -1 ? args[deployIndex + 1] : null
18
- const hasIonic = args.includes('--ionic')
19
- const hasTauri = args.includes('--tauri')
20
- const force = args.includes('--force')
18
+ const hasIonic = args.includes("--ionic")
19
+ const hasTauri = args.includes("--tauri")
20
+ const force = args.includes("--force")
21
21
 
22
22
  const projectDir = join(process.cwd(), projectName)
23
23
 
@@ -25,22 +25,22 @@ async function main () {
25
25
 
26
26
  // 1. Crear con Vite
27
27
  try {
28
- console.log(chalk.blue(' [1/5] Creando base Vite + React + TS...'))
28
+ console.log(chalk.blue(" [1/5] Creando base Vite + React + TS..."))
29
29
  execSync(
30
- `npx create-vite@latest ${projectName} --template react-ts ${force ? '--force' : ''}`,
30
+ `npx create-vite@latest ${projectName} --template react-ts ${force ? "--force" : ""}`,
31
31
  {
32
- stdio: 'pipe',
33
- cwd: process.cwd()
32
+ stdio: "pipe",
33
+ cwd: process.cwd(),
34
34
  }
35
35
  )
36
- console.log(chalk.green(' ✅ Base Vite creada'))
36
+ console.log(chalk.green(" ✅ Base Vite creada"))
37
37
  } catch {
38
- console.log(chalk.yellow(' ⚠️ Vite base ya existe o falló. Continuando...'))
38
+ console.log(chalk.yellow(" ⚠️ Vite base ya existe o falló. Continuando..."))
39
39
  }
40
40
 
41
41
  // 2. Limpiar boilerplate predecible
42
- console.log(chalk.blue(' [2/5] Limpiando boilerplate innecesario...'))
43
- const toDelete = ['src/App.css', 'src/assets', 'public/vite.svg']
42
+ console.log(chalk.blue(" [2/5] Limpiando boilerplate innecesario..."))
43
+ const toDelete = ["src/App.css", "src/assets", "public/vite.svg"]
44
44
  for (const file of toDelete) {
45
45
  const fullPath = join(projectDir, file)
46
46
  if (existsSync(fullPath)) {
@@ -54,34 +54,34 @@ async function main () {
54
54
 
55
55
  export default App
56
56
  `
57
- writeFileSync(join(projectDir, 'src/App.tsx'), appContent, 'utf-8')
57
+ writeFileSync(join(projectDir, "src/App.tsx"), appContent, "utf-8")
58
58
 
59
59
  // 3. Instalar dependencias adicionales
60
60
  if (deps.length > 0) {
61
- console.log(chalk.blue(` [3/5] Instalando dependencias: ${deps.join(', ')}...`))
61
+ console.log(chalk.blue(` [3/5] Instalando dependencias: ${deps.join(", ")}...`))
62
62
  try {
63
- execSync(`npm install ${deps.join(' ')}`, { stdio: 'pipe', cwd: projectDir })
64
- console.log(chalk.green(' ✅ Dependencias instaladas'))
63
+ execSync(`npm install ${deps.join(" ")}`, { stdio: "pipe", cwd: projectDir })
64
+ console.log(chalk.green(" ✅ Dependencias instaladas"))
65
65
  } catch {
66
66
  console.log(
67
- chalk.yellow(' ⚠️ Error instalando dependencias. Continúa con npm install manual.')
67
+ chalk.yellow(" ⚠️ Error instalando dependencias. Continúa con npm install manual.")
68
68
  )
69
69
  }
70
70
  }
71
71
 
72
72
  // 4. Copiar scaffolds
73
- console.log(chalk.blue(' [4/5] Copiando archivos de configuración...'))
74
- const scaffoldsDir = join(__dirname, '..', 'scaffolds')
73
+ console.log(chalk.blue(" [4/5] Copiando archivos de configuración..."))
74
+ const scaffoldsDir = join(__dirname, "..", "scaffolds")
75
75
 
76
76
  const scaffoldFiles = [
77
- ['tailwind.config.js', 'tailwind.config.js'],
78
- ['prompt-lang.json', 'prompt-lang.json']
77
+ ["tailwind.config.js", "tailwind.config.js"],
78
+ ["prompt-lang.json", "prompt-lang.json"],
79
79
  ]
80
80
 
81
- if (deploy === 'railway') scaffoldFiles.push(['railway.json', 'railway.json'])
82
- if (deploy === 'netlify') scaffoldFiles.push(['netlify.toml', 'netlify.toml'])
83
- if (hasIonic) scaffoldFiles.push(['capacitor.config.ts', 'capacitor.config.ts'])
84
- if (hasTauri) scaffoldFiles.push(['tauri.conf.json', 'tauri.conf.json'])
81
+ if (deploy === "railway") scaffoldFiles.push(["railway.json", "railway.json"])
82
+ if (deploy === "netlify") scaffoldFiles.push(["netlify.toml", "netlify.toml"])
83
+ if (hasIonic) scaffoldFiles.push(["capacitor.config.ts", "capacitor.config.ts"])
84
+ if (hasTauri) scaffoldFiles.push(["tauri.conf.json", "tauri.conf.json"])
85
85
 
86
86
  for (const [src, dest] of scaffoldFiles) {
87
87
  const srcPath = join(scaffoldsDir, src)
@@ -93,43 +93,43 @@ export default App
93
93
  }
94
94
 
95
95
  // 5. Configurar package.json con scripts descriptivos
96
- console.log(chalk.blue(' [5/5] Agregando scripts descriptivos...'))
97
- const pkgPath = join(projectDir, 'package.json')
96
+ console.log(chalk.blue(" [5/5] Agregando scripts descriptivos..."))
97
+ const pkgPath = join(projectDir, "package.json")
98
98
  if (existsSync(pkgPath)) {
99
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
99
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"))
100
100
  const descriptiveScripts = {
101
- 'dev:start': 'vite',
102
- 'dev:preview': 'vite preview',
103
- 'build:prod': 'vite build',
104
- 'build:analyze': 'vite build --analyze',
105
- 'lint:check': 'eslint src --ext .ts,.tsx',
106
- 'lint:fix': 'eslint src --ext .ts,.tsx --fix',
107
- 'type:check': 'tsc --noEmit',
108
- 'test:unit': 'vitest run',
109
- 'test:watch': 'vitest',
110
- 'test:coverage': 'vitest run --coverage',
111
- 'validate:all': 'npm run lint:check && npm run type:check && npm run test:unit'
101
+ "dev:start": "vite",
102
+ "dev:preview": "vite preview",
103
+ "build:prod": "vite build",
104
+ "build:analyze": "vite build --analyze",
105
+ "lint:check": "eslint src --ext .ts,.tsx",
106
+ "lint:fix": "eslint src --ext .ts,.tsx --fix",
107
+ "type:check": "tsc --noEmit",
108
+ "test:unit": "vitest run",
109
+ "test:watch": "vitest",
110
+ "test:coverage": "vitest run --coverage",
111
+ "validate:all": "npm run lint:check && npm run type:check && npm run test:unit",
112
112
  }
113
113
  pkg.scripts = { ...descriptiveScripts, ...pkg.scripts }
114
- writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2) }\n`, 'utf-8')
115
- console.log(chalk.green(' ✅ Scripts descriptivos agregados'))
114
+ writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf-8")
115
+ console.log(chalk.green(" ✅ Scripts descriptivos agregados"))
116
116
  }
117
117
 
118
118
  // Ionic plug
119
119
  if (hasIonic) {
120
- console.log(chalk.blue(' 🔌 Integrando Ionic...'))
120
+ console.log(chalk.blue(" 🔌 Integrando Ionic..."))
121
121
  try {
122
- execSync('npx cap init App com.app.app --web-dir=dist', { stdio: 'pipe', cwd: projectDir })
123
- execSync('npx cap add android', { stdio: 'pipe', cwd: projectDir })
124
- console.log(chalk.green(' ✅ Ionic/Capacitor configurado'))
122
+ execSync("npx cap init App com.app.app --web-dir=dist", { stdio: "pipe", cwd: projectDir })
123
+ execSync("npx cap add android", { stdio: "pipe", cwd: projectDir })
124
+ console.log(chalk.green(" ✅ Ionic/Capacitor configurado"))
125
125
  } catch {
126
- console.log(chalk.yellow(' ⚠️ Error en setup Ionic. Configura manualmente.'))
126
+ console.log(chalk.yellow(" ⚠️ Error en setup Ionic. Configura manualmente."))
127
127
  }
128
128
  }
129
129
 
130
130
  console.log(chalk.cyan(`\n✅ ${projectName} listo!`))
131
131
  console.log(chalk.cyan(` cd ${projectName}`))
132
- console.log(chalk.cyan(' npm run dev:start\n'))
132
+ console.log(chalk.cyan(" npm run dev:start\n"))
133
133
  }
134
134
 
135
135
  main().catch(console.error)
package/bin/lint.js CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { readFileSync, existsSync } from 'fs'
4
- import { join } from 'path'
5
- import { lintFile } from '../src/utils/annotations.js'
6
- import chalk from 'chalk'
3
+ import { readFileSync, existsSync } from "fs"
4
+ import { join } from "path"
5
+ import { lintFile } from "../src/utils/annotations.js"
6
+ import chalk from "chalk"
7
7
 
8
- const targetFile = join(process.cwd(), process.argv[2] || '')
8
+ const targetFile = join(process.cwd(), process.argv[2] || "")
9
9
 
10
10
  if (!targetFile || !existsSync(targetFile)) {
11
- console.log(chalk.red('❌ Archivo no encontrado'))
12
- console.log('Uso: node bin/lint.js <archivo>')
11
+ console.log(chalk.red("❌ Archivo no encontrado"))
12
+ console.log("Uso: node bin/lint.js <archivo>")
13
13
  process.exit(1)
14
14
  }
15
15
 
16
- const content = readFileSync(targetFile, 'utf-8')
16
+ const content = readFileSync(targetFile, "utf-8")
17
17
  const { annotations, errors, warnings } = lintFile(content)
18
18
 
19
19
  if (annotations.length === 0) {
20
- console.log(chalk.cyan('📭 Sin anotaciones PromptLang en este archivo'))
20
+ console.log(chalk.cyan("📭 Sin anotaciones PromptLang en este archivo"))
21
21
  process.exit(0)
22
22
  }
23
23
 
@@ -25,9 +25,9 @@ console.log(chalk.cyan(`\n🔍 Anotaciones encontradas: ${annotations.length}\n`
25
25
 
26
26
  for (const ann of annotations) {
27
27
  const argsStr = ann.args.length
28
- ? ann.args.map((a) => (a.key ? `${a.key}: ${a.value}` : a.value)).join(', ')
29
- : ''
30
- console.log(` @${ann.name}${argsStr ? `(${argsStr})` : ''}`)
28
+ ? ann.args.map((a) => (a.key ? `${a.key}: ${a.value}` : a.value)).join(", ")
29
+ : ""
30
+ console.log(` @${ann.name}${argsStr ? `(${argsStr})` : ""}`)
31
31
  }
32
32
 
33
33
  if (errors.length > 0) {
@@ -45,5 +45,5 @@ if (warnings.length > 0) {
45
45
  }
46
46
 
47
47
  if (errors.length === 0 && warnings.length === 0) {
48
- console.log(chalk.green('\n✅ Todas las anotaciones válidas\n'))
48
+ console.log(chalk.green("\n✅ Todas las anotaciones válidas\n"))
49
49
  }
@@ -3,7 +3,7 @@
3
3
  ## 1. Resumen corto
4
4
  - Proyecto: openPrompt-Lang — context engine de anotaciones y templates para desarrollo asistido por IA
5
5
  - Objetivo: IA local especializada en desarrollo asistido con contexto reducido y pasos pequeños.
6
- - Versión: 0.8.0 (CLI), módulos de lenguaje v1.0.0–1.1.0
6
+ - Versión: 0.10.1 (CLI), módulos de lenguaje v1.0.0–1.1.0
7
7
 
8
8
  ## 2. Stack técnico
9
9
  - Frontend: React 19 + TypeScript + Vite 7 + Tailwind v4
@@ -30,18 +30,36 @@ controller, service, route, middleware, model, repository, util, type, prisma, s
30
30
  Controller, Service, Repository, DTOs, Entity, GlobalExceptionHandler, FeignClient, KafkaConfig
31
31
 
32
32
  ## 4. Base de conocimiento
33
- - **10 dominios**: payments, mobile-pwa, systems, qa, frontend, backend, accessibility, algorithms, fundamentals, architecture
33
+ - **13 dominios**: payments, mobile-pwa, systems, qa, frontend, backend, accessibility, algorithms, fundamentals, architecture, typescript, saas, restaurant
34
34
  - **13 playbooks**: flow-integration, capacitor-setup, rust-ownership, scrum-workflow, frontend-react, backend-nodejs, accessibility-wcag, algorithms-patterns, fundamentals-programs, spa-auth-flow, api-rest-design, db-schema-design, microservice-architecture
35
- - **33 fuentes** de conocimiento (libros/docs procesados)
35
+ - **35 fuentes** de conocimiento (libros/docs + 2 proyectos reales extraídos)
36
+ - **10 sistemas de conocimiento**: react-fullstack-app, sistema-pagos-chile, microservicios-spring, app-movil-offline, sistema-restaurant-pos, api-rest-robusta, accesibilidad-wcag-chile, typescript-avanzado, microservicios-multi-lenguaje, saas-pos-chileno
36
37
 
37
- ## 5. Comandos clave
38
+ ## 5. Comandos OPL
38
39
  ```bash
39
- npx openPrompt-Lang validate # Validar anotaciones
40
- npx openPrompt-Lang lang list # Listar módulos
41
- npx openPrompt-Lang lang index react # Ver templates de un módulo
42
- npx openPrompt-Lang teach <id> # Aprender de un template
43
- npx openPrompt-Lang knowledge list # Listar conocimiento
44
- npx openPrompt-Lang knowledge search # Buscar en conocimiento
40
+ # Navegación de conocimiento
41
+ opl index [path] # Navegar por niveles
42
+ opl read <dominio>/<id> # Leer contenido (--chapter n --full)
43
+ opl search <query> # Búsqueda híbrida (+ detecta sistema)
44
+ opl system [name] # Explorar sistemas de conocimiento
45
+ opl graph [concept] # Grafo de relaciones
46
+
47
+ # Evaluación de proyectos
48
+ opl assess [path] # PRA score 0-100
49
+ opl assess --verbose # 7 dimensiones × 28 criterios
50
+ opl assess --save # Guardar reporte JSON
51
+
52
+ # Configuración y sesiones
53
+ opl init --knowledge # Biblioteca personal ~/.opl/knowledge/
54
+ opl session doc/close/diff # Gestión de sesiones
55
+ opl doc flow/framework # Documentación (Mermaid, FRAMEWORK.md)
56
+ opl upgrade # Migrar configuración
57
+
58
+ # Templates y validación
59
+ npx openPrompt-Lang validate # Validar anotaciones
60
+ npx openPrompt-Lang lang list # Listar módulos
61
+ npx openPrompt-Lang teach <id> # Aprender de un template
62
+ npx openPrompt-Lang qa-gen # Generar tests de regresión
45
63
  ```
46
64
 
47
65
  ## 6. Referencia canónica