refacil-sdd-ai 4.2.3 → 4.3.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/README.md +239 -214
- package/agents/auditor.md +182 -184
- package/agents/debugger.md +201 -204
- package/agents/implementer.md +150 -149
- package/agents/investigator.md +80 -89
- package/agents/proposer.md +219 -124
- package/agents/tester.md +140 -144
- package/agents/validator.md +153 -145
- package/bin/cli.js +158 -116
- package/lib/bus/askFulfillment.js +17 -17
- package/lib/bus/broker.js +599 -599
- package/lib/bus/ui/app.js +318 -318
- package/lib/commands/sdd.js +433 -0
- package/lib/hooks.js +236 -236
- package/lib/installer.js +55 -1
- package/lib/methodology-migration-pending.js +101 -136
- package/package.json +4 -6
- package/skills/apply/SKILL.md +122 -120
- package/skills/archive/SKILL.md +101 -107
- package/skills/ask/SKILL.md +78 -78
- package/skills/attend/SKILL.md +70 -70
- package/skills/bug/SKILL.md +121 -117
- package/skills/explore/SKILL.md +61 -63
- package/skills/guide/SKILL.md +79 -79
- package/skills/inbox/SKILL.md +43 -43
- package/skills/join/SKILL.md +82 -82
- package/skills/prereqs/BUS-CROSS-REPO.md +55 -55
- package/skills/prereqs/METHODOLOGY-CONTRACT.md +122 -115
- package/skills/prereqs/SKILL.md +30 -37
- package/skills/propose/SKILL.md +91 -102
- package/skills/reply/SKILL.md +44 -44
- package/skills/review/SKILL.md +135 -126
- package/skills/review/checklist-back.md +92 -92
- package/skills/review/checklist-front.md +72 -72
- package/skills/review/checklist.md +114 -114
- package/skills/say/SKILL.md +38 -38
- package/skills/setup/SKILL.md +85 -141
- package/skills/setup/troubleshooting.md +38 -35
- package/skills/test/SKILL.md +86 -94
- package/skills/test/testing-patterns.md +63 -63
- package/skills/up-code/SKILL.md +108 -108
- package/skills/update/SKILL.md +109 -132
- package/skills/verify/SKILL.md +128 -132
- package/templates/compact-guidance.md +45 -45
- package/templates/methodology-guide.md +46 -42
- package/config/openspec-config.yaml +0 -8
- package/skills/prereqs/OPENSPEC-DELTAS.md +0 -51
package/bin/cli.js
CHANGED
|
@@ -13,6 +13,7 @@ const {
|
|
|
13
13
|
installSkills,
|
|
14
14
|
installAgents,
|
|
15
15
|
removeSkills,
|
|
16
|
+
removeOpenspecLegacyAssets,
|
|
16
17
|
createClaudeMd,
|
|
17
18
|
createCursorRules,
|
|
18
19
|
readRepoVersion,
|
|
@@ -24,6 +25,7 @@ const {
|
|
|
24
25
|
const { installHooks, uninstallHooks, cleanLegacySettingsHooks } = require('../lib/hooks');
|
|
25
26
|
const { handleCompact } = require('../lib/commands/compact');
|
|
26
27
|
const { handleBus } = require('../lib/commands/bus');
|
|
28
|
+
const { handleSdd, autoMigrateOpenspec } = require('../lib/commands/sdd');
|
|
27
29
|
const { syncIgnoreFiles } = require('../lib/ignore-files');
|
|
28
30
|
const { methodologyMigrationPending } = require('../lib/methodology-migration-pending');
|
|
29
31
|
|
|
@@ -46,7 +48,7 @@ function writePendingUpdateFlag(root, fromVersion, toVersion) {
|
|
|
46
48
|
} catch (_) {}
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
/**
|
|
51
|
+
/** Clears `.refacil-pending-update` if there is no longer a pending migration (stale flags or skill sync without migration). */
|
|
50
52
|
function clearStalePendingUpdateFlag(root) {
|
|
51
53
|
const flagPath = path.join(root, '.refacil-pending-update');
|
|
52
54
|
if (!fs.existsSync(flagPath)) return;
|
|
@@ -78,9 +80,9 @@ function notifyUpdate() {
|
|
|
78
80
|
return;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
const fromLabel = info.from ? `v${info.from}` : 'version
|
|
83
|
+
const fromLabel = info.from ? `v${info.from}` : 'previous version';
|
|
82
84
|
|
|
83
|
-
//
|
|
85
|
+
// If the user is already running /refacil:update, let it through and clear the flag
|
|
84
86
|
const prompt = readStdinPrompt();
|
|
85
87
|
if (prompt.includes('refacil:update') || prompt.includes('refacil/update')) {
|
|
86
88
|
try { fs.unlinkSync(flagPath); } catch (_) {}
|
|
@@ -88,13 +90,13 @@ function notifyUpdate() {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
if (!info.shown) {
|
|
91
|
-
//
|
|
93
|
+
// First time: block so the user sees it clearly
|
|
92
94
|
try { fs.writeFileSync(flagPath, JSON.stringify({ ...info, shown: true })); } catch (_) {}
|
|
93
95
|
const userMsg =
|
|
94
|
-
`[refacil-sdd-ai]
|
|
95
|
-
`
|
|
96
|
-
` •
|
|
97
|
-
` • No:
|
|
96
|
+
`[refacil-sdd-ai] Methodology update detected (${fromLabel} → v${info.to}).\n` +
|
|
97
|
+
`Your message was paused. Do you want to apply the pending migrations before continuing?\n` +
|
|
98
|
+
` • Yes: run /refacil:update\n` +
|
|
99
|
+
` • No: resend your previous message to continue without updating.`;
|
|
98
100
|
if (isCursor) {
|
|
99
101
|
process.stdout.write(JSON.stringify({ continue: false, user_message: userMsg }) + '\n');
|
|
100
102
|
} else {
|
|
@@ -103,12 +105,12 @@ function notifyUpdate() {
|
|
|
103
105
|
}
|
|
104
106
|
process.exit(2);
|
|
105
107
|
} else {
|
|
106
|
-
//
|
|
108
|
+
// Second time: let through and notify the LLM (only Claude Code supports context injection)
|
|
107
109
|
try { fs.unlinkSync(flagPath); } catch (_) {}
|
|
108
110
|
if (!isCursor) {
|
|
109
111
|
console.log(
|
|
110
|
-
`[refacil-sdd-ai]
|
|
111
|
-
`
|
|
112
|
+
`[refacil-sdd-ai] IMPORTANT: there is a pending SDD-AI methodology update (${fromLabel} → v${info.to}). ` +
|
|
113
|
+
`Before responding to the user, ask them if they want to run /refacil:update now.`,
|
|
112
114
|
);
|
|
113
115
|
}
|
|
114
116
|
}
|
|
@@ -137,11 +139,11 @@ function syncRepoSkillsIfStale(globalVersion) {
|
|
|
137
139
|
const repoVersion = readRepoVersion(projectRoot);
|
|
138
140
|
if (repoVersion === globalVersion) return null;
|
|
139
141
|
|
|
140
|
-
//
|
|
142
|
+
// Repo has newer skills than the installed package — do not downgrade
|
|
141
143
|
if (semverGt(repoVersion, globalVersion)) {
|
|
142
144
|
process.stderr.write(
|
|
143
|
-
`[refacil-sdd-ai]
|
|
144
|
-
`
|
|
145
|
+
`[refacil-sdd-ai] Repo uses methodology v${repoVersion} but the global package is v${globalVersion}. ` +
|
|
146
|
+
`Run: npm update -g refacil-sdd-ai\n`,
|
|
145
147
|
);
|
|
146
148
|
return null;
|
|
147
149
|
}
|
|
@@ -167,10 +169,10 @@ function migrationPendingCmd() {
|
|
|
167
169
|
if (wantJson) {
|
|
168
170
|
process.stdout.write(`${JSON.stringify({ pending, reasons })}\n`);
|
|
169
171
|
} else if (pending) {
|
|
170
|
-
console.log('
|
|
172
|
+
console.log(' Pending methodology migrations:');
|
|
171
173
|
for (const r of reasons) console.log(` - ${r}`);
|
|
172
174
|
} else {
|
|
173
|
-
console.log('
|
|
175
|
+
console.log(' No pending methodology migrations (criteria aligned with hooks and /refacil:update).');
|
|
174
176
|
}
|
|
175
177
|
clearStalePendingUpdateFlag(projectRoot);
|
|
176
178
|
process.exit(pending ? 1 : 0);
|
|
@@ -179,18 +181,33 @@ function migrationPendingCmd() {
|
|
|
179
181
|
function checkUpdate() {
|
|
180
182
|
clearStalePendingUpdateFlag(projectRoot);
|
|
181
183
|
|
|
184
|
+
try {
|
|
185
|
+
autoMigrateOpenspec(projectRoot);
|
|
186
|
+
} catch (err) {
|
|
187
|
+
process.stderr.write(`[refacil-sdd-ai] Could not migrate openspec/ to refacil-sdd/: ${err.message}\n`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const legacyRemoved = removeOpenspecLegacyAssets(projectRoot);
|
|
192
|
+
if (legacyRemoved > 0) {
|
|
193
|
+
process.stderr.write(`[refacil-sdd-ai] Removed ${legacyRemoved} legacy OpenSpec assets (openspec-* skills, opsx-* commands)\n`);
|
|
194
|
+
}
|
|
195
|
+
} catch (err) {
|
|
196
|
+
process.stderr.write(`[refacil-sdd-ai] Could not remove legacy OpenSpec assets: ${err.message}\n`);
|
|
197
|
+
}
|
|
198
|
+
|
|
182
199
|
const { execSync } = require('child_process');
|
|
183
200
|
let localVersion = getPackageVersion(packageRoot);
|
|
184
201
|
|
|
185
202
|
try {
|
|
186
203
|
syncCompactGuidance(projectRoot, packageRoot);
|
|
187
204
|
} catch (err) {
|
|
188
|
-
process.stderr.write(`[refacil-sdd-ai]
|
|
205
|
+
process.stderr.write(`[refacil-sdd-ai] Could not sync compact-guidance: ${err.message}\n`);
|
|
189
206
|
}
|
|
190
207
|
|
|
191
208
|
cleanLegacySettingsHooks(projectRoot);
|
|
192
209
|
|
|
193
|
-
//
|
|
210
|
+
// Step 1: update the global package if a newer version is available on npm
|
|
194
211
|
try {
|
|
195
212
|
const latest = execSync('npm view refacil-sdd-ai version', {
|
|
196
213
|
encoding: 'utf8',
|
|
@@ -204,8 +221,8 @@ function checkUpdate() {
|
|
|
204
221
|
localVersion = latest;
|
|
205
222
|
} catch (_) {
|
|
206
223
|
console.log(
|
|
207
|
-
`[refacil-sdd-ai]
|
|
208
|
-
`
|
|
224
|
+
`[refacil-sdd-ai] A new version is available (v${localVersion} -> v${latest}) but the automatic update failed. ` +
|
|
225
|
+
`Run manually: npm update -g refacil-sdd-ai && refacil-sdd-ai update`,
|
|
209
226
|
);
|
|
210
227
|
}
|
|
211
228
|
}
|
|
@@ -213,21 +230,21 @@ function checkUpdate() {
|
|
|
213
230
|
// Silent: sin internet o registry no disponible
|
|
214
231
|
}
|
|
215
232
|
|
|
216
|
-
//
|
|
233
|
+
// Step 2: sync repo skills with the (now updated) package
|
|
217
234
|
const syncResult = syncRepoSkillsIfStale(localVersion);
|
|
218
235
|
if (syncResult && !syncResult.failed) {
|
|
219
|
-
const fromLabel = syncResult.from ? `v${syncResult.from}` : 'version
|
|
236
|
+
const fromLabel = syncResult.from ? `v${syncResult.from}` : 'unknown version';
|
|
220
237
|
console.log(
|
|
221
|
-
`[refacil-sdd-ai]
|
|
222
|
-
'
|
|
238
|
+
`[refacil-sdd-ai] Repo skills synced (${fromLabel} -> v${syncResult.to}). ` +
|
|
239
|
+
'Restart the Claude Code or Cursor session to pick up the changes.',
|
|
223
240
|
);
|
|
224
241
|
if (methodologyMigrationPending(projectRoot).pending) {
|
|
225
242
|
writePendingUpdateFlag(projectRoot, syncResult.from, syncResult.to);
|
|
226
243
|
}
|
|
227
244
|
} else if (syncResult && syncResult.failed) {
|
|
228
245
|
console.log(
|
|
229
|
-
`[refacil-sdd-ai]
|
|
230
|
-
'
|
|
246
|
+
`[refacil-sdd-ai] Repo skills are out of date with the global package (v${syncResult.to}) ` +
|
|
247
|
+
'but automatic sync failed. Run manually: refacil-sdd-ai update',
|
|
231
248
|
);
|
|
232
249
|
}
|
|
233
250
|
}
|
|
@@ -246,7 +263,9 @@ function checkReview() {
|
|
|
246
263
|
const command = (input.tool_input && input.tool_input.command) || '';
|
|
247
264
|
if (!command.match(/git\s+push/)) return;
|
|
248
265
|
|
|
249
|
-
const
|
|
266
|
+
const sddChangesDir = path.join(projectRoot, 'refacil-sdd', 'changes');
|
|
267
|
+
const legacyChangesDir = path.join(projectRoot, 'openspec', 'changes');
|
|
268
|
+
const changesDir = fs.existsSync(sddChangesDir) ? sddChangesDir : legacyChangesDir;
|
|
250
269
|
if (!fs.existsSync(changesDir)) return;
|
|
251
270
|
|
|
252
271
|
const entries = fs.readdirSync(changesDir, { withFileTypes: true });
|
|
@@ -264,14 +283,14 @@ function checkReview() {
|
|
|
264
283
|
const names = missing.map((e) => e.name).join(', ');
|
|
265
284
|
const reason =
|
|
266
285
|
missing.length === 1
|
|
267
|
-
? `[refacil-sdd-ai] Review
|
|
268
|
-
'
|
|
269
|
-
'
|
|
270
|
-
'
|
|
271
|
-
: `[refacil-sdd-ai]
|
|
272
|
-
'
|
|
273
|
-
'
|
|
274
|
-
'
|
|
286
|
+
? `[refacil-sdd-ai] Review pending for: ${names}. ` +
|
|
287
|
+
'Stop the push and run /refacil:review on that change before pushing code. ' +
|
|
288
|
+
'If the review passes, retry the git push. ' +
|
|
289
|
+
'If the review requires corrections, report the findings to the user and DO NOT retry the push.'
|
|
290
|
+
: `[refacil-sdd-ai] Multiple changes without approved review: ${names}. ` +
|
|
291
|
+
'Stop the push and ask the user to explicitly select which change they want to push. ' +
|
|
292
|
+
'Then run /refacil:review <change-name> for that specific change and retry the push. ' +
|
|
293
|
+
'Do not run automatic review without explicit selection when there is more than one pending change.';
|
|
275
294
|
console.log(JSON.stringify({ decision: 'block', reason }));
|
|
276
295
|
}
|
|
277
296
|
}
|
|
@@ -279,7 +298,7 @@ function checkReview() {
|
|
|
279
298
|
// --- High-level commands ---
|
|
280
299
|
|
|
281
300
|
function init() {
|
|
282
|
-
console.log('\n refacil-sdd-ai:
|
|
301
|
+
console.log('\n refacil-sdd-ai: Initializing SDD-AI methodology...\n');
|
|
283
302
|
|
|
284
303
|
const nodeOk = checkNodeVersion();
|
|
285
304
|
if (nodeOk) console.log(` Node.js ${process.version} OK`);
|
|
@@ -288,18 +307,18 @@ function init() {
|
|
|
288
307
|
if (claudeCheck.ok === true) {
|
|
289
308
|
console.log(` Claude Code ${claudeCheck.version} OK`);
|
|
290
309
|
} else if (claudeCheck.ok === false) {
|
|
291
|
-
console.log(`\n
|
|
292
|
-
console.log('
|
|
293
|
-
console.log('
|
|
294
|
-
console.log('
|
|
310
|
+
console.log(`\n WARNING: Claude Code ${claudeCheck.version} detected.`);
|
|
311
|
+
console.log(' The compact-bash hook requires Claude Code >= 2.1.89 for silent rewrite.');
|
|
312
|
+
console.log(' It will still install on older versions but the rewrite will have no effect.');
|
|
313
|
+
console.log(' Update with: npm install -g @anthropic-ai/claude-code\n');
|
|
295
314
|
}
|
|
296
315
|
|
|
297
316
|
const count = installSkills(packageRoot, projectRoot);
|
|
298
|
-
console.log(` ${count} skills
|
|
317
|
+
console.log(` ${count} skills installed in .claude/skills/ and .cursor/skills/`);
|
|
299
318
|
|
|
300
319
|
const agentsCount = installAgents(packageRoot, projectRoot);
|
|
301
320
|
if (agentsCount > 0) {
|
|
302
|
-
console.log(` ${agentsCount} sub-
|
|
321
|
+
console.log(` ${agentsCount} sub-agents installed in .claude/agents/ and .cursor/agents/`);
|
|
303
322
|
}
|
|
304
323
|
|
|
305
324
|
writeRepoVersion(projectRoot, getPackageVersion(packageRoot));
|
|
@@ -308,56 +327,62 @@ function init() {
|
|
|
308
327
|
if (createCursorRules(packageRoot, projectRoot)) console.log(' .cursorrules OK');
|
|
309
328
|
|
|
310
329
|
if (installHooks('.claude', projectRoot)) {
|
|
311
|
-
console.log(' Hook check-update
|
|
330
|
+
console.log(' Hook check-update added to .claude/settings.json');
|
|
312
331
|
}
|
|
313
332
|
if (installHooks('.cursor', projectRoot)) {
|
|
314
|
-
console.log(' Hook check-update
|
|
333
|
+
console.log(' Hook check-update added to .cursor/settings.json');
|
|
315
334
|
}
|
|
316
335
|
|
|
317
336
|
try {
|
|
318
337
|
const ignoreResult = syncIgnoreFiles(projectRoot);
|
|
319
338
|
const s = ignoreResult.claude;
|
|
320
339
|
if (s.status === 'created') {
|
|
321
|
-
console.log(' .claudeignore
|
|
340
|
+
console.log(' .claudeignore and .cursorignore created');
|
|
322
341
|
} else if (s.status === 'updated') {
|
|
323
|
-
console.log(` .claudeignore
|
|
342
|
+
console.log(` .claudeignore and .cursorignore updated (${s.added} entries added)`);
|
|
324
343
|
} else {
|
|
325
|
-
console.log(' .claudeignore
|
|
344
|
+
console.log(' .claudeignore and .cursorignore are up to date');
|
|
326
345
|
}
|
|
327
346
|
} catch (err) {
|
|
328
|
-
console.error(`
|
|
347
|
+
console.error(` Warning: could not sync ignore files: ${err.message}`);
|
|
329
348
|
}
|
|
330
349
|
|
|
331
350
|
try {
|
|
332
351
|
const result = syncCompactGuidance(projectRoot, packageRoot);
|
|
333
352
|
if (result.status === 'appended') {
|
|
334
|
-
console.log('
|
|
353
|
+
console.log(' compact-guidance block added to AGENTS.md');
|
|
335
354
|
} else if (result.status === 'replaced') {
|
|
336
|
-
console.log('
|
|
355
|
+
console.log(' compact-guidance block updated in AGENTS.md');
|
|
337
356
|
}
|
|
338
357
|
} catch (err) {
|
|
339
|
-
console.error(`
|
|
358
|
+
console.error(` Warning: could not sync compact-guidance: ${err.message}`);
|
|
340
359
|
}
|
|
341
360
|
|
|
342
|
-
console.log('\n
|
|
343
|
-
console.log(' 1.
|
|
344
|
-
console.log(' (
|
|
345
|
-
console.log(' 2.
|
|
346
|
-
console.log(' (
|
|
347
|
-
console.log(' Nota: /refacil:setup tambien instalara los comandos de OpenSpec (opsx:*).');
|
|
348
|
-
console.log(' Los comandos refacil:* y opsx:* coexisten sin conflicto.');
|
|
349
|
-
console.log(' El equipo debe usar los refacil:* como interfaz principal.\n');
|
|
361
|
+
console.log('\n Next steps:\n');
|
|
362
|
+
console.log(' 1. RESTART your Claude Code or Cursor session');
|
|
363
|
+
console.log(' (new skills are not detected until the session is restarted)\n');
|
|
364
|
+
console.log(' 2. Run: /refacil:setup');
|
|
365
|
+
console.log(' (generates AGENTS.md for your project)\n');
|
|
350
366
|
}
|
|
351
367
|
|
|
352
368
|
function update() {
|
|
353
|
-
console.log('\n refacil-sdd-ai:
|
|
369
|
+
console.log('\n refacil-sdd-ai: Updating skills...\n');
|
|
354
370
|
|
|
355
371
|
const count = installSkills(packageRoot, projectRoot);
|
|
356
|
-
console.log(` ${count} skills
|
|
372
|
+
console.log(` ${count} skills updated in .claude/skills/ and .cursor/skills/`);
|
|
357
373
|
|
|
358
374
|
const agentsCount = installAgents(packageRoot, projectRoot);
|
|
359
375
|
if (agentsCount > 0) {
|
|
360
|
-
console.log(` ${agentsCount} sub-
|
|
376
|
+
console.log(` ${agentsCount} sub-agents updated in .claude/agents/ and .cursor/agents/`);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
try {
|
|
380
|
+
const legacyRemoved = removeOpenspecLegacyAssets(projectRoot);
|
|
381
|
+
if (legacyRemoved > 0) {
|
|
382
|
+
console.log(` ${legacyRemoved} legacy OpenSpec assets removed (openspec-* skills, opsx-* commands)`);
|
|
383
|
+
}
|
|
384
|
+
} catch (err) {
|
|
385
|
+
process.stderr.write(`[refacil-sdd-ai] Could not remove legacy OpenSpec assets: ${err.message}\n`);
|
|
361
386
|
}
|
|
362
387
|
|
|
363
388
|
writeRepoVersion(projectRoot, getPackageVersion(packageRoot));
|
|
@@ -366,92 +391,93 @@ function update() {
|
|
|
366
391
|
createCursorRules(packageRoot, projectRoot);
|
|
367
392
|
|
|
368
393
|
if (installHooks('.claude', projectRoot)) {
|
|
369
|
-
console.log(' Hook check-update
|
|
394
|
+
console.log(' Hook check-update added to .claude/settings.json');
|
|
370
395
|
}
|
|
371
396
|
if (installHooks('.cursor', projectRoot)) {
|
|
372
|
-
console.log(' Hook check-update
|
|
397
|
+
console.log(' Hook check-update added to .cursor/settings.json');
|
|
373
398
|
}
|
|
374
399
|
|
|
375
400
|
try {
|
|
376
401
|
const ignoreResult = syncIgnoreFiles(projectRoot);
|
|
377
402
|
const s = ignoreResult.claude;
|
|
378
403
|
if (s.status === 'created') {
|
|
379
|
-
console.log(' .claudeignore
|
|
404
|
+
console.log(' .claudeignore and .cursorignore created');
|
|
380
405
|
} else if (s.status === 'updated') {
|
|
381
|
-
console.log(` .claudeignore
|
|
406
|
+
console.log(` .claudeignore and .cursorignore updated (${s.added} entries added)`);
|
|
382
407
|
} else {
|
|
383
|
-
console.log(' .claudeignore
|
|
408
|
+
console.log(' .claudeignore and .cursorignore are up to date');
|
|
384
409
|
}
|
|
385
410
|
} catch (err) {
|
|
386
|
-
console.error(`
|
|
411
|
+
console.error(` Warning: could not sync ignore files: ${err.message}`);
|
|
387
412
|
}
|
|
388
413
|
|
|
389
414
|
try {
|
|
390
415
|
const result = syncCompactGuidance(projectRoot, packageRoot);
|
|
391
416
|
if (result.status === 'appended') {
|
|
392
|
-
console.log('
|
|
417
|
+
console.log(' compact-guidance block added to AGENTS.md');
|
|
393
418
|
} else if (result.status === 'replaced') {
|
|
394
|
-
console.log('
|
|
419
|
+
console.log(' compact-guidance block updated in AGENTS.md');
|
|
395
420
|
}
|
|
396
421
|
} catch (err) {
|
|
397
|
-
console.error(`
|
|
422
|
+
console.error(` Warning: could not sync compact-guidance: ${err.message}`);
|
|
398
423
|
}
|
|
399
424
|
|
|
400
|
-
console.log('\n
|
|
425
|
+
console.log('\n RESTART your Claude Code or Cursor session to apply the changes.\n');
|
|
401
426
|
}
|
|
402
427
|
|
|
403
428
|
function clean() {
|
|
404
|
-
console.log('\n refacil-sdd-ai:
|
|
429
|
+
console.log('\n refacil-sdd-ai: Removing skills...\n');
|
|
405
430
|
|
|
406
431
|
const count = removeSkills(projectRoot);
|
|
407
|
-
console.log(` ${count} skills
|
|
432
|
+
console.log(` ${count} skills removed from .claude/skills/ and .cursor/skills/`);
|
|
408
433
|
|
|
409
434
|
if (uninstallHooks('.claude', projectRoot)) {
|
|
410
|
-
console.log('
|
|
435
|
+
console.log(' SDD-AI hooks removed from .claude/settings.json');
|
|
411
436
|
} else {
|
|
412
|
-
console.log(' No
|
|
437
|
+
console.log(' No SDD-AI hooks found to remove in .claude/settings.json.');
|
|
413
438
|
}
|
|
414
439
|
if (uninstallHooks('.cursor', projectRoot)) {
|
|
415
|
-
console.log('
|
|
440
|
+
console.log(' SDD-AI hooks removed from .cursor/settings.json');
|
|
416
441
|
}
|
|
417
442
|
|
|
418
443
|
try {
|
|
419
444
|
const result = removeCompactGuidance(projectRoot);
|
|
420
445
|
if (result.status === 'removed') {
|
|
421
|
-
console.log('
|
|
446
|
+
console.log(' compact-guidance block removed from AGENTS.md');
|
|
422
447
|
}
|
|
423
448
|
} catch (err) {
|
|
424
|
-
console.error(`
|
|
449
|
+
console.error(` Warning: could not clean compact-guidance: ${err.message}`);
|
|
425
450
|
}
|
|
426
451
|
|
|
427
|
-
console.log(' AGENTS.md, CLAUDE.md
|
|
428
|
-
console.log('\n
|
|
429
|
-
console.log('
|
|
452
|
+
console.log(' AGENTS.md, CLAUDE.md and .cursorrules were not removed.');
|
|
453
|
+
console.log('\n Note: if you have openspec/ in the repo, migrate first with: refacil-sdd-ai sdd status');
|
|
454
|
+
console.log(' (the openspec/ → refacil-sdd/ migration is automatic on any sdd subcommand)');
|
|
455
|
+
console.log(' To remove the openspec/ directory after migrating: rm -rf openspec/\n');
|
|
430
456
|
}
|
|
431
457
|
|
|
432
458
|
function help() {
|
|
433
459
|
console.log(`
|
|
434
|
-
refacil-sdd-ai —
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
init
|
|
438
|
-
update Re-
|
|
439
|
-
migration-pending
|
|
440
|
-
check-update
|
|
441
|
-
notify-update
|
|
442
|
-
check-review
|
|
443
|
-
compact-bash
|
|
444
|
-
compact
|
|
445
|
-
compact stats -
|
|
446
|
-
compact disable -
|
|
447
|
-
compact enable - Re-
|
|
448
|
-
compact clear-log -
|
|
449
|
-
bus
|
|
450
|
-
bus start -
|
|
451
|
-
bus stop -
|
|
452
|
-
bus status -
|
|
453
|
-
bus serve - (
|
|
454
|
-
bus join --room <
|
|
460
|
+
refacil-sdd-ai — SDD-AI Methodology
|
|
461
|
+
|
|
462
|
+
Commands:
|
|
463
|
+
init Install skills in .claude/ and .cursor/, create CLAUDE.md and .cursorrules
|
|
464
|
+
update Re-copy skills (to update to a new package version)
|
|
465
|
+
migration-pending Same validation as hooks/notify-update: list migrations (exit 1 if any; --json)
|
|
466
|
+
check-update Sync skills and compact-guidance at session start (SessionStart hook)
|
|
467
|
+
notify-update Notify methodology migration only if applicable (UserPromptSubmit hook)
|
|
468
|
+
check-review Verify that review has been completed (used by PreToolUse hook)
|
|
469
|
+
compact-bash Rewrite bare Bash commands to reduce tokens (used by PreToolUse hook)
|
|
470
|
+
compact Subcommands for the compact-bash hook:
|
|
471
|
+
compact stats - Full stats (hook + already-compact) and estimated savings
|
|
472
|
+
compact disable - Temporarily disable rewrite
|
|
473
|
+
compact enable - Re-enable rewrite
|
|
474
|
+
compact clear-log - Clear the history log
|
|
475
|
+
bus Subcommands for the inter-agent chat room (refacil-bus):
|
|
476
|
+
bus start - Start the local broker (auto-spawn detached)
|
|
477
|
+
bus stop - Stop the broker
|
|
478
|
+
bus status - Show port, pid, uptime of the broker
|
|
479
|
+
bus serve - (internal) Run the broker in foreground
|
|
480
|
+
bus join --room <room> [--session <s>] [--intro "..."]
|
|
455
481
|
bus leave [--session <s>]
|
|
456
482
|
bus say --text "..." [--session <s>]
|
|
457
483
|
bus ask --to <name|all|*|everyone> --text "..." [--wait N] [--session <s>]
|
|
@@ -459,21 +485,29 @@ function help() {
|
|
|
459
485
|
bus history [--n N] [--session <s>]
|
|
460
486
|
bus inbox [--session <s>]
|
|
461
487
|
bus rooms
|
|
462
|
-
bus watch <session> [--room <
|
|
463
|
-
bus attend [--timeout N] (
|
|
464
|
-
bus view (
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
488
|
+
bus watch <session> [--room <room>] (live panel, no tokens)
|
|
489
|
+
bus attend [--timeout N] (listen for directed questions)
|
|
490
|
+
bus view (open the web UI in the browser)
|
|
491
|
+
sdd Subcommands for managing SDD-AI artifacts in refacil-sdd/:
|
|
492
|
+
sdd new-change <name> Create a change with proposal/design/tasks/specs scaffold
|
|
493
|
+
sdd archive <name> Archive a change to refacil-sdd/changes/archive/
|
|
494
|
+
sdd list [--json] List active changes with review status
|
|
495
|
+
sdd status <name> [--json] Artifact and task status of a change
|
|
496
|
+
sdd mark-reviewed <name> Write .review-passed (requires --verdict and --summary)
|
|
497
|
+
sdd tasks-update <name> Mark task N as completed (--task N --done)
|
|
498
|
+
sdd validate-name <name> Validate change name format
|
|
499
|
+
clean Remove skills and SDD-AI hooks from .claude/settings.json and .cursor/settings.json
|
|
500
|
+
help Show this help
|
|
501
|
+
|
|
502
|
+
Full flow:
|
|
469
503
|
1. npm install -g refacil-sdd-ai
|
|
470
504
|
2. refacil-sdd-ai init
|
|
471
|
-
3.
|
|
472
|
-
4.
|
|
505
|
+
3. RESTART the Claude Code or Cursor session
|
|
506
|
+
4. Run: /refacil:setup (generates AGENTS.md for your project)
|
|
473
507
|
|
|
474
|
-
|
|
475
|
-
- Node.js >= 20.19.0
|
|
476
|
-
- Claude Code >= 2.1.89 (
|
|
508
|
+
Requirements:
|
|
509
|
+
- Node.js >= 20.19.0
|
|
510
|
+
- Claude Code >= 2.1.89 (required by compact-bash for silent rewrite) or Cursor
|
|
477
511
|
`);
|
|
478
512
|
}
|
|
479
513
|
|
|
@@ -481,6 +515,11 @@ function help() {
|
|
|
481
515
|
|
|
482
516
|
const command = process.argv[2] || 'help';
|
|
483
517
|
|
|
518
|
+
if (command === '--version' || command === '-v') {
|
|
519
|
+
console.log(getPackageVersion(packageRoot));
|
|
520
|
+
process.exit(0);
|
|
521
|
+
}
|
|
522
|
+
|
|
484
523
|
switch (command) {
|
|
485
524
|
case 'init':
|
|
486
525
|
init();
|
|
@@ -509,6 +548,9 @@ switch (command) {
|
|
|
509
548
|
case 'bus':
|
|
510
549
|
handleBus(process.argv[3], process.argv.slice(4), packageRoot);
|
|
511
550
|
break;
|
|
551
|
+
case 'sdd':
|
|
552
|
+
handleSdd(process.argv[3], process.argv.slice(4));
|
|
553
|
+
break;
|
|
512
554
|
case 'clean':
|
|
513
555
|
clean();
|
|
514
556
|
break;
|
|
@@ -518,7 +560,7 @@ switch (command) {
|
|
|
518
560
|
help();
|
|
519
561
|
break;
|
|
520
562
|
default:
|
|
521
|
-
console.error(`
|
|
563
|
+
console.error(` Unknown command: ${command}`);
|
|
522
564
|
help();
|
|
523
565
|
process.exit(1);
|
|
524
566
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Indica si el `ask` ya tiene una respuesta que lo cierra para este hilo.
|
|
5
|
-
* Para el mismo correlationId con varios destinatarios (@all), solo cuenta
|
|
6
|
-
* la respuesta emitida por la sesión que recibió ese ask (ask.to).
|
|
7
|
-
*/
|
|
8
|
-
function askHasMatchingReply(messages, ask) {
|
|
9
|
-
if (!ask || ask.kind !== 'ask' || !ask.correlationId) return true;
|
|
10
|
-
return messages.some((m) => {
|
|
11
|
-
if (m.kind !== 'reply' || m.correlationId !== ask.correlationId) return false;
|
|
12
|
-
if (ask.to) return m.from === ask.to;
|
|
13
|
-
return m.to === ask.from;
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = { askHasMatchingReply };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Indica si el `ask` ya tiene una respuesta que lo cierra para este hilo.
|
|
5
|
+
* Para el mismo correlationId con varios destinatarios (@all), solo cuenta
|
|
6
|
+
* la respuesta emitida por la sesión que recibió ese ask (ask.to).
|
|
7
|
+
*/
|
|
8
|
+
function askHasMatchingReply(messages, ask) {
|
|
9
|
+
if (!ask || ask.kind !== 'ask' || !ask.correlationId) return true;
|
|
10
|
+
return messages.some((m) => {
|
|
11
|
+
if (m.kind !== 'reply' || m.correlationId !== ask.correlationId) return false;
|
|
12
|
+
if (ask.to) return m.from === ask.to;
|
|
13
|
+
return m.to === ask.from;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { askHasMatchingReply };
|