refacil-sdd-ai 2.8.0 → 2.8.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/README.md +7 -38
- package/bin/cli.js +88 -3
- package/lib/bus/broker.js +7 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -554,13 +554,6 @@ refacil-sdd-ai clean
|
|
|
554
554
|
npm uninstall -g refacil-sdd-ai
|
|
555
555
|
```
|
|
556
556
|
|
|
557
|
-
## Tecnologias
|
|
558
|
-
|
|
559
|
-
- [OpenSpec](https://github.com/Fission-AI/OpenSpec) — Framework de especificaciones
|
|
560
|
-
- [AGENTS.md](https://agents.md/) — Estandar universal de instrucciones para IA
|
|
561
|
-
- [Claude Code](https://claude.ai/code) — CLI de Anthropic
|
|
562
|
-
- [Cursor](https://cursor.sh) — IDE con IA
|
|
563
|
-
|
|
564
557
|
## refacil-bus
|
|
565
558
|
|
|
566
559
|
Chat room local entre agentes. Permite que distintas sesiones de Claude Code o Cursor corriendo en repos diferentes se coordinen por texto plano — **sin compartir archivos, contexto ni tokens entre repos**. Cada agente responde desde el conocimiento de su propio repositorio.
|
|
@@ -712,37 +705,13 @@ El CLI prioriza ese bloque literal. Si no existe, hace fallback a `package.json`
|
|
|
712
705
|
- Sin autenticacion: cualquier proceso local puede conectar al broker (por diseño, es solo loopback y a demanda del dev).
|
|
713
706
|
- Persistencia 7 dias en `~/.refacil-sdd-ai/bus/<sala>/inbox.jsonl` (rotacion lazy al escribir).
|
|
714
707
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
-
|
|
719
|
-
-
|
|
720
|
-
-
|
|
721
|
-
-
|
|
722
|
-
- Presentacion automatica al unirse usando bloque marcado en `AGENTS.md` con fallback a `package.json`
|
|
723
|
-
- Soporte de conversacion automatica LLM ↔ LLM via `ask --wait` + `attend` en el otro lado
|
|
724
|
-
- Funciona identico en Claude Code y Cursor (sin hooks, todo via skills)
|
|
725
|
-
|
|
726
|
-
**v2.6.0** — Fase 2 del hook `compact-bash`:
|
|
727
|
-
- 11 reglas nuevas: `eslint`, `biome check`, `tsc`, `prettier --check`, `npm audit`, `npm ls`, `cargo build/test/check`, `go test`, `mvn test`, `gradle test`, `ps aux` (total: 19 reglas)
|
|
728
|
-
- Telemetria local en `~/.refacil-sdd-ai/compact.log`
|
|
729
|
-
- Subcomandos `compact stats | disable | enable | clear-log`
|
|
730
|
-
- `ps-aux` solo se activa en Unix (Linux/Mac); en Windows la regla no interviene
|
|
731
|
-
|
|
732
|
-
**v2.5.0** — Fase 1 del hook `compact-bash`:
|
|
733
|
-
- Hook `PreToolUse` que reescribe silenciosamente comandos Bash bare via `updatedInput` (requiere Claude Code >= 2.1.89)
|
|
734
|
-
- Reglas iniciales: git log/status/diff/show, docker logs, npm/yarn/pnpm test, jest, pytest
|
|
735
|
-
- Escape mecanismo `COMPACT=0 <cmd>`
|
|
736
|
-
|
|
737
|
-
**v2.4.0** — Reduccion de tokens en la metodologia:
|
|
738
|
-
- Boilerplate "Antes de empezar" unificado en 9 skills
|
|
739
|
-
- Validacion de OpenSpec simplificada en `prereqs/SKILL.md`
|
|
740
|
-
- Templates consolidados (`claude-md.md` + `cursorrules.md` → `methodology-guide.md` unico)
|
|
741
|
-
- Compactacion de `review/SKILL.md`, `bug/SKILL.md`, `test/SKILL.md`
|
|
742
|
-
|
|
743
|
-
**v2.3.0** — Bloque `compact-guidance` auto-gestionado en `AGENTS.md`:
|
|
744
|
-
- Hook `SessionStart` sincroniza el bloque en cada sesion
|
|
745
|
-
- Fuente de verdad: `templates/compact-guidance.md`
|
|
708
|
+
|
|
709
|
+
## Tecnologias
|
|
710
|
+
|
|
711
|
+
- [OpenSpec](https://github.com/Fission-AI/OpenSpec) — Framework de especificaciones
|
|
712
|
+
- [AGENTS.md](https://agents.md/) — Estandar universal de instrucciones para IA
|
|
713
|
+
- [Claude Code](https://claude.ai/code) — CLI de Anthropic
|
|
714
|
+
- [Cursor](https://cursor.sh) — IDE con IA
|
|
746
715
|
|
|
747
716
|
## Licencia
|
|
748
717
|
|
package/bin/cli.js
CHANGED
|
@@ -125,6 +125,42 @@ function createCursorRules() {
|
|
|
125
125
|
);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
const REPO_VERSION_FILES = ['.claude/.sdd-version', '.cursor/.sdd-version'];
|
|
129
|
+
|
|
130
|
+
function readRepoVersion(rootDir) {
|
|
131
|
+
for (const rel of REPO_VERSION_FILES) {
|
|
132
|
+
const p = path.join(rootDir, rel);
|
|
133
|
+
try {
|
|
134
|
+
const raw = fs.readFileSync(p, 'utf8').trim();
|
|
135
|
+
if (raw) return raw;
|
|
136
|
+
} catch (_) {
|
|
137
|
+
// continuar al siguiente
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function writeRepoVersion(rootDir, version) {
|
|
144
|
+
for (const rel of REPO_VERSION_FILES) {
|
|
145
|
+
const p = path.join(rootDir, rel);
|
|
146
|
+
const parent = path.dirname(p);
|
|
147
|
+
if (!fs.existsSync(parent)) continue;
|
|
148
|
+
try {
|
|
149
|
+
fs.writeFileSync(p, String(version) + '\n');
|
|
150
|
+
} catch (_) {
|
|
151
|
+
// tolerante
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getPackageVersion() {
|
|
157
|
+
try {
|
|
158
|
+
return require(path.join(packageRoot, 'package.json')).version;
|
|
159
|
+
} catch (_) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
128
164
|
function removeSkills() {
|
|
129
165
|
let removed = 0;
|
|
130
166
|
for (const skill of SKILLS) {
|
|
@@ -304,9 +340,39 @@ function uninstallHook() {
|
|
|
304
340
|
|
|
305
341
|
// --- Check update ---
|
|
306
342
|
|
|
343
|
+
function repoIsInitialized() {
|
|
344
|
+
return (
|
|
345
|
+
fs.existsSync(path.join(projectRoot, '.claude', 'skills')) ||
|
|
346
|
+
fs.existsSync(path.join(projectRoot, '.cursor', 'skills'))
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function syncRepoSkillsIfStale(globalVersion) {
|
|
351
|
+
// Si el paquete global ya está en globalVersion pero este repo tiene skills
|
|
352
|
+
// de una versión anterior (porque otro repo disparó el auto-upgrade), hay
|
|
353
|
+
// que re-copiarlas aquí. Idem si nunca se marcó la versión en este repo.
|
|
354
|
+
if (!repoIsInitialized()) return null;
|
|
355
|
+
const repoVersion = readRepoVersion(projectRoot);
|
|
356
|
+
if (repoVersion === globalVersion) return null;
|
|
357
|
+
|
|
358
|
+
const { execSync } = require('child_process');
|
|
359
|
+
const localCli = path.join(packageRoot, 'bin', 'cli.js');
|
|
360
|
+
try {
|
|
361
|
+
execSync(`"${process.execPath}" "${localCli}" update`, {
|
|
362
|
+
encoding: 'utf8',
|
|
363
|
+
timeout: 30000,
|
|
364
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
365
|
+
});
|
|
366
|
+
writeRepoVersion(projectRoot, globalVersion);
|
|
367
|
+
return { from: repoVersion, to: globalVersion };
|
|
368
|
+
} catch (_) {
|
|
369
|
+
return { from: repoVersion, to: globalVersion, failed: true };
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
307
373
|
function checkUpdate() {
|
|
308
374
|
const { execSync } = require('child_process');
|
|
309
|
-
const localVersion =
|
|
375
|
+
const localVersion = getPackageVersion();
|
|
310
376
|
|
|
311
377
|
// Always ensure AGENTS.md has current compact-guidance block (silent unless error)
|
|
312
378
|
try {
|
|
@@ -317,6 +383,24 @@ function checkUpdate() {
|
|
|
317
383
|
);
|
|
318
384
|
}
|
|
319
385
|
|
|
386
|
+
// Paso 1: sincronizar skills del repo actual si quedaron desfasadas respecto
|
|
387
|
+
// al paquete global (pasa cuando otro repo ya disparó el auto-upgrade).
|
|
388
|
+
const syncResult = syncRepoSkillsIfStale(localVersion);
|
|
389
|
+
if (syncResult && !syncResult.failed) {
|
|
390
|
+
const fromLabel = syncResult.from ? `v${syncResult.from}` : 'version desconocida';
|
|
391
|
+
console.log(
|
|
392
|
+
`[refacil-sdd-ai] Skills de este repo sincronizadas (${fromLabel} -> v${syncResult.to}). ` +
|
|
393
|
+
'Reinicia la sesion de Claude Code o Cursor para detectar los cambios.',
|
|
394
|
+
);
|
|
395
|
+
} else if (syncResult && syncResult.failed) {
|
|
396
|
+
console.log(
|
|
397
|
+
`[refacil-sdd-ai] Skills de este repo estan desactualizadas respecto al paquete global (v${syncResult.to}) ` +
|
|
398
|
+
'pero la sincronizacion automatica fallo. Ejecuta manualmente: refacil-sdd-ai update',
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Paso 2: chequear si hay version nueva en npm y, si la hay, actualizar
|
|
403
|
+
// global + copiar skills al repo actual.
|
|
320
404
|
try {
|
|
321
405
|
const latest = execSync('npm view refacil-sdd-ai version', {
|
|
322
406
|
encoding: 'utf8',
|
|
@@ -326,7 +410,6 @@ function checkUpdate() {
|
|
|
326
410
|
|
|
327
411
|
if (!latest || latest === localVersion) return;
|
|
328
412
|
|
|
329
|
-
// Auto-upgrade: the hook does it itself, LLM only sees the result
|
|
330
413
|
try {
|
|
331
414
|
execSync('npm update -g refacil-sdd-ai', {
|
|
332
415
|
encoding: 'utf8',
|
|
@@ -338,11 +421,11 @@ function checkUpdate() {
|
|
|
338
421
|
timeout: 30000,
|
|
339
422
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
340
423
|
});
|
|
424
|
+
writeRepoVersion(projectRoot, latest);
|
|
341
425
|
console.log(
|
|
342
426
|
`[refacil-sdd-ai] La metodologia SDD-AI se actualizo automaticamente de v${localVersion} a v${latest}. Skills y hooks sincronizados.`,
|
|
343
427
|
);
|
|
344
428
|
} catch (_) {
|
|
345
|
-
// Upgrade failed — inform so the user can do it manually
|
|
346
429
|
console.log(
|
|
347
430
|
`[refacil-sdd-ai] Hay una nueva version disponible (v${localVersion} -> v${latest}) pero la actualizacion automatica fallo. ` +
|
|
348
431
|
`Informa al usuario que ejecute manualmente: npm update -g refacil-sdd-ai && refacil-sdd-ai update`,
|
|
@@ -433,6 +516,7 @@ function init() {
|
|
|
433
516
|
// Install skills
|
|
434
517
|
const count = installSkills();
|
|
435
518
|
console.log(` ${count} skills instaladas en .claude/skills/ y .cursor/skills/`);
|
|
519
|
+
writeRepoVersion(projectRoot, getPackageVersion());
|
|
436
520
|
|
|
437
521
|
// Create or update CLAUDE.md
|
|
438
522
|
if (createClaudeMd()) {
|
|
@@ -475,6 +559,7 @@ function update() {
|
|
|
475
559
|
console.log('\n refacil-sdd-ai: Actualizando skills...\n');
|
|
476
560
|
const count = installSkills();
|
|
477
561
|
console.log(` ${count} skills actualizadas en .claude/skills/ y .cursor/skills/`);
|
|
562
|
+
writeRepoVersion(projectRoot, getPackageVersion());
|
|
478
563
|
|
|
479
564
|
// Ensure hook is installed (for users updating from versions without hook)
|
|
480
565
|
if (installHook()) {
|
package/lib/bus/broker.js
CHANGED
|
@@ -205,6 +205,7 @@ function handleJoin(state, ws, data) {
|
|
|
205
205
|
|
|
206
206
|
// Si la sesión ya existe en otra sala, sacarla primero
|
|
207
207
|
const existing = state.sessions.get(session);
|
|
208
|
+
const isReturningToSameRoom = !!(existing && existing.room === room);
|
|
208
209
|
if (existing && existing.room && existing.room !== room) {
|
|
209
210
|
leaveRoom(state, session);
|
|
210
211
|
}
|
|
@@ -212,8 +213,13 @@ function handleJoin(state, ws, data) {
|
|
|
212
213
|
const meta = existing || {};
|
|
213
214
|
meta.repo = repo || meta.repo || null;
|
|
214
215
|
meta.room = room;
|
|
215
|
-
meta.lastSeen = nowIso();
|
|
216
216
|
meta.watchOnly = false;
|
|
217
|
+
// Primer join o cambio de sala → lastSeen = ahora (sin backlog).
|
|
218
|
+
// Reingreso a la misma sala tras desconectar → preservar lastSeen existente
|
|
219
|
+
// para que /inbox traiga los mensajes perdidos mientras estuvo fuera.
|
|
220
|
+
if (!isReturningToSameRoom || !meta.lastSeen) {
|
|
221
|
+
meta.lastSeen = nowIso();
|
|
222
|
+
}
|
|
217
223
|
if (!meta.wss) meta.wss = new Set();
|
|
218
224
|
state.sessions.set(session, meta);
|
|
219
225
|
ws._refacilSession = session;
|
package/package.json
CHANGED