@saulwade/swl-ses 1.3.1 → 1.3.2

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/CLAUDE.md CHANGED
@@ -1,4 +1,4 @@
1
- # CLAUDE.md — @saulwade/swl-ses v1.3.1
1
+ # CLAUDE.md — @saulwade/swl-ses v1.3.2
2
2
 
3
3
  ## Reglas de máxima prioridad (aplican SIEMPRE, sin excepción)
4
4
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # swl-ses v1.3.1
1
+ # swl-ses v1.3.2
2
2
 
3
3
  > El paquete anterior `@saulwadeleon/swl-software-engineering-system` está deprecado. Migrar a `@saulwade/swl-ses` (npmjs.org canónico) o `@saul-wade/swl-ses` (mirror en GitHub Packages) — el CLI `swl-ses` no cambia.
4
4
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "lockfileVersion": 1,
3
- "generatedAt": "2026-05-11T03:35:46.021Z",
3
+ "generatedAt": "2026-05-11T05:48:19.419Z",
4
4
  "skillsCount": 155,
5
5
  "lockHash": "sha256:92e415132658a0de593795e73b5561d952194f39a138fdb429f16743bb5837ff",
6
6
  "skills": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saulwade/swl-ses",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Sistema de ingenieria de software auto-evolutivo multi-runtime polyglot con 59 agentes, 155 habilidades, 43 comandos, 64 reglas y 41 hooks. Soporta 11 lenguajes y 5 runtimes: Claude Code, Copilot, OpenCode, Codex y Gemini CLI. 100% en espanol (Mexico). Incluye gateway bidireccional con relay Telegram a Claude Code.",
5
5
  "bin": {
6
6
  "swl-ses": "bin/swl-ses.js",
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swl-ses",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Sistema de ingenieria de software auto-evolutivo multi-runtime polyglot. 59 agentes, 155 habilidades, 43 comandos, 64 reglas y 41 hooks. 62 librerias. 11 lenguajes. Soporta Claude Code, Copilot, OpenCode, Codex y Gemini CLI.",
5
5
  "author": "Saul Wade Leon",
6
6
  "license": "MIT",
@@ -72,6 +72,55 @@ function _resolverUsuario(username, user) {
72
72
  return (raw && _RX_USUARIO_SEGURO.test(raw)) ? raw : '$env:USERNAME';
73
73
  }
74
74
 
75
+ /**
76
+ * Construye el script de PowerShell que registra el Scheduled Task.
77
+ *
78
+ * Pura — no ejecuta nada, solo retorna el string del script. Esto permite
79
+ * testear el contenido sin invocar PowerShell real, y aísla las invariantes
80
+ * críticas del script (presencia de `-UserId` en `New-ScheduledTaskPrincipal`,
81
+ * orden de parámetros, valores escapados).
82
+ *
83
+ * Invariantes obligatorias:
84
+ * - `New-ScheduledTaskPrincipal` DEBE incluir `-UserId` cuando se usa
85
+ * `-LogonType Interactive`. PowerShell rechaza la llamada con
86
+ * ParameterBindingException si falta. Bug histórico 2026-05-11.
87
+ * - `nodePath` y `daemonPath` se escapan duplicando comillas simples
88
+ * (convención PowerShell para strings literales).
89
+ * - El nombre de usuario se resuelve y valida con `_resolverUsuario()`,
90
+ * que cae a `$env:USERNAME` si el valor tiene caracteres peligrosos.
91
+ *
92
+ * @param {string} nodeExe — path absoluto a node.exe
93
+ * @param {string} rutaDaemon — path absoluto al daemon JS
94
+ * @returns {string} script de PowerShell listo para `_ejecutarPowerShell`
95
+ */
96
+ function _construirScriptPS(nodeExe, rutaDaemon) {
97
+ const nodePath = String(nodeExe).replace(/'/g, "''");
98
+ const daemonPath = String(rutaDaemon).replace(/'/g, "''");
99
+ // REM-3: validar USERNAME antes de interpolarlo. _resolverUsuario rechaza
100
+ // caracteres peligrosos y cae a '$env:USERNAME' si el valor es sospechoso.
101
+ const usuario = _resolverUsuario();
102
+
103
+ return `
104
+ $action = New-ScheduledTaskAction -Execute '${nodePath}' -Argument '"${daemonPath}"'
105
+ $trigger = New-ScheduledTaskTrigger -AtLogOn -User '${usuario}'
106
+ $settings = New-ScheduledTaskSettingsSet \`
107
+ -StartWhenAvailable \`
108
+ -RestartCount 3 \`
109
+ -RestartInterval (New-TimeSpan -Minutes 2) \`
110
+ -AllowStartIfOnBatteries \`
111
+ -DontStopIfGoingOnBatteries \`
112
+ -ExecutionTimeLimit ([TimeSpan]::Zero)
113
+ $principal = New-ScheduledTaskPrincipal -UserId '${usuario}' -LogonType Interactive -RunLevel Limited
114
+ Register-ScheduledTask \`
115
+ -TaskName '${TASK_NAME}' \`
116
+ -Action $action \`
117
+ -Trigger $trigger \`
118
+ -Settings $settings \`
119
+ -Principal $principal \`
120
+ -Force
121
+ `.trim();
122
+ }
123
+
75
124
  /**
76
125
  * Construye la ruta absoluta al daemon bin/swl-telegram-bot.js
77
126
  * a partir de __dirname (scripts/lib/), NO hardcodeada.
@@ -178,33 +227,7 @@ function install() {
178
227
 
179
228
  // Construir el script de PowerShell con parámetros en variables separadas
180
229
  // Nunca concatenar dentro del script — los valores ya están en variables escapadas
181
- const nodePath = nodeExe.replace(/'/g, "''"); // Escape de comillas simples en PS
182
- const daemonPath = rutaDaemon.replace(/'/g, "''");
183
-
184
- // REM-3: validar USERNAME antes de interpolarlo en el script de PowerShell.
185
- // _resolverUsuario usa un regex para rechazar caracteres peligrosos y cae a
186
- // '$env:USERNAME' si el valor es sospechoso.
187
- const usuario = _resolverUsuario();
188
-
189
- const psScript = `
190
- $action = New-ScheduledTaskAction -Execute '${nodePath}' -Argument '"${daemonPath}"'
191
- $trigger = New-ScheduledTaskTrigger -AtLogOn -User '${usuario}'
192
- $settings = New-ScheduledTaskSettingsSet \`
193
- -StartWhenAvailable \`
194
- -RestartCount 3 \`
195
- -RestartInterval (New-TimeSpan -Minutes 2) \`
196
- -AllowStartIfOnBatteries \`
197
- -DontStopIfGoingOnBatteries \`
198
- -ExecutionTimeLimit ([TimeSpan]::Zero)
199
- $principal = New-ScheduledTaskPrincipal -LogonType Interactive -RunLevel Limited
200
- Register-ScheduledTask \`
201
- -TaskName '${TASK_NAME}' \`
202
- -Action $action \`
203
- -Trigger $trigger \`
204
- -Settings $settings \`
205
- -Principal $principal \`
206
- -Force
207
- `.trim();
230
+ const psScript = _construirScriptPS(nodeExe, rutaDaemon);
208
231
 
209
232
  _log('INFO', 'Registrando Scheduled Task vía PowerShell (RunLevel: Limited, sin elevación)...');
210
233
  const resultado = _ejecutarPowerShell(psScript);
@@ -304,4 +327,4 @@ if ($task) { $task.State } else { 'NOT_FOUND' }
304
327
  return { instalado: true, estado: estadoNorm };
305
328
  }
306
329
 
307
- module.exports = { install, uninstall, status, _resolverUsuario };
330
+ module.exports = { install, uninstall, status, _resolverUsuario, _construirScriptPS };