sdd-gl 0.6.0 → 0.6.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.es.md +29 -2
- package/README.md +29 -2
- package/bin/sdd.js +15 -3
- package/mcp/server.js +23 -5
- package/package.json +5 -3
package/README.es.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/sdd-gl)
|
|
6
|
+
[](CHANGELOG.md)
|
|
6
7
|
[](LICENSE)
|
|
7
8
|
[](mcp/sdd-gl-mcp-spec.md)
|
|
8
9
|
[](https://docs.claude.ai/code)
|
|
@@ -285,7 +286,30 @@ Sigue esta guía paso a paso para configurar y comenzar a utilizar SDD-GL en tu
|
|
|
285
286
|
|
|
286
287
|
### 2. Elige tu Método de Instalación
|
|
287
288
|
|
|
288
|
-
####
|
|
289
|
+
#### 📦 Método 0: paquete npm (recomendado)
|
|
290
|
+
Publicado como **`sdd-gl`** en npm — sin clonar ni spec de GitHub:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
npm install -g sdd-gl # instala dos comandos: sdd (CLI) y sdd-gl-mcp (servidor)
|
|
294
|
+
sdd --help # verificar
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Para la configuración de un cliente MCP, apuntá al binario del servidor:
|
|
298
|
+
|
|
299
|
+
```json
|
|
300
|
+
{
|
|
301
|
+
"mcpServers": {
|
|
302
|
+
"sdd-gl": {
|
|
303
|
+
"command": "npx",
|
|
304
|
+
"args": ["-y", "--package", "sdd-gl", "sdd-gl-mcp"]
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
> Un paquete con dos binarios no se resuelve solo por el nombre del paquete, así que `npx` siempre nombra el binario: `--package sdd-gl sdd-gl-mcp`.
|
|
311
|
+
|
|
312
|
+
#### 🌐 Método 1: Servidor MCP Universal desde GitHub (Cursor, Windsurf, OpenCode, Warp, Claude Desktop, VS Code)
|
|
289
313
|
Sin necesidad de clonar repositorios manualmente. Añade el servidor MCP directamente desde GitHub a la configuración de tu IDE o cliente de terminal (`~/.cursor/mcp.json`, `claude_desktop_config.json`, configuración de OpenCode o Cline MCP):
|
|
290
314
|
|
|
291
315
|
```json
|
|
@@ -780,6 +804,7 @@ sdd-gl/
|
|
|
780
804
|
├── docs/
|
|
781
805
|
│ ├── index.html ← Dashboard público del showcase (solo examples/, nunca los contratos privados).
|
|
782
806
|
│ ├── INSTALACION.md ← Instalación paso a paso por plataforma.
|
|
807
|
+
│ ├── DEPLOY.md ← Checklist de publicación para mantenedores.
|
|
783
808
|
│ └── assets/
|
|
784
809
|
│ └── dashboard-sample.png ← Captura real de un proyecto de ejemplo.
|
|
785
810
|
├── protocol/
|
|
@@ -801,6 +826,8 @@ sdd-gl/
|
|
|
801
826
|
├── examples/
|
|
802
827
|
│ └── contracts/ ← Contratos showcase públicos (curados y resueltos).
|
|
803
828
|
├── contracts/ ← Specs de trabajo locales (gitignored — privadas).
|
|
829
|
+
├── scripts/
|
|
830
|
+
│ └── release.js ← Sube la versión en manifiestos y badges, y verifica la deriva.
|
|
804
831
|
├── test-sandbox/ ← 15 suites: core, CLI, métricas, uso, CI, interop y fixtures.
|
|
805
832
|
├── .claude/
|
|
806
833
|
│ ├── agents/ ← 6 adaptadores de agente (español).
|
package/README.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/sdd-gl)
|
|
6
|
+
[](CHANGELOG.md)
|
|
6
7
|
[](LICENSE)
|
|
7
8
|
[](mcp/sdd-gl-mcp-spec.md)
|
|
8
9
|
[](https://docs.claude.ai/code)
|
|
@@ -284,7 +285,30 @@ Follow this step-by-step guide to configure and start using SDD-GL in your prefe
|
|
|
284
285
|
|
|
285
286
|
### 2. Choose Your Installation Method
|
|
286
287
|
|
|
287
|
-
####
|
|
288
|
+
#### 📦 Method 0: npm package (recommended)
|
|
289
|
+
Published as **`sdd-gl`** on npm — no cloning, no GitHub spec:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
npm install -g sdd-gl # installs two commands: sdd (CLI) and sdd-gl-mcp (server)
|
|
293
|
+
sdd --help # verify
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
For an MCP client configuration, point it at the server binary:
|
|
297
|
+
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"mcpServers": {
|
|
301
|
+
"sdd-gl": {
|
|
302
|
+
"command": "npx",
|
|
303
|
+
"args": ["-y", "--package", "sdd-gl", "sdd-gl-mcp"]
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
> A package with two binaries cannot be resolved by package name alone, so `npx` always names the binary: `--package sdd-gl sdd-gl-mcp`.
|
|
310
|
+
|
|
311
|
+
#### 🌐 Method 1: Universal MCP Server from GitHub (Cursor, Windsurf, OpenCode, Warp, Claude Desktop, VS Code)
|
|
288
312
|
No repository cloning needed. Add the MCP server directly from GitHub to your IDE / terminal client configuration (`~/.cursor/mcp.json`, `claude_desktop_config.json`, OpenCode settings, or Cline MCP settings):
|
|
289
313
|
|
|
290
314
|
```json
|
|
@@ -779,6 +803,7 @@ sdd-gl/
|
|
|
779
803
|
├── docs/
|
|
780
804
|
│ ├── index.html ← Public showcase dashboard (examples/ only, never the private contracts).
|
|
781
805
|
│ ├── INSTALACION.md ← Step-by-step installation per platform.
|
|
806
|
+
│ ├── DEPLOY.md ← Release checklist for maintainers.
|
|
782
807
|
│ └── assets/
|
|
783
808
|
│ └── dashboard-sample.png ← Real capture of an example project.
|
|
784
809
|
├── protocol/
|
|
@@ -800,6 +825,8 @@ sdd-gl/
|
|
|
800
825
|
├── examples/
|
|
801
826
|
│ └── contracts/ ← Public showcase contracts (curated and resolved).
|
|
802
827
|
├── contracts/ ← Local working specs (gitignored — private).
|
|
828
|
+
├── scripts/
|
|
829
|
+
│ └── release.js ← Version bump across manifests and README badges, plus the drift check.
|
|
803
830
|
├── test-sandbox/ ← 15 suites: core, CLI, metrics, usage, CI, interop and fixtures.
|
|
804
831
|
├── .claude/
|
|
805
832
|
│ ├── agents/ ← 6 agent adapters (Spanish).
|
package/bin/sdd.js
CHANGED
|
@@ -32,7 +32,7 @@ const ROOT = rootFlag ? path.resolve(rootFlag) : process.cwd();
|
|
|
32
32
|
|
|
33
33
|
process.env.SDD_PROJECT_ROOT = ROOT;
|
|
34
34
|
|
|
35
|
-
const { handleToolCall, TOOLS } = require('../mcp/server.js');
|
|
35
|
+
const { handleToolCall, TOOLS, isContractText, looksLikeContract } = require('../mcp/server.js');
|
|
36
36
|
|
|
37
37
|
// CLI usage is real usage of the methodology: it is counted and attributed to the
|
|
38
38
|
// contract type it serves (feature/fix) when a contract is involved.
|
|
@@ -588,17 +588,28 @@ function commandDoctor() {
|
|
|
588
588
|
|
|
589
589
|
const unreadable = [];
|
|
590
590
|
const stalled = [];
|
|
591
|
+
const ignored = [];
|
|
592
|
+
let contracts = 0;
|
|
591
593
|
|
|
592
594
|
if (fs.existsSync(contractsDir)) {
|
|
593
595
|
for (const name of fs.readdirSync(contractsDir).filter(entry => entry.toLowerCase().endsWith('.md'))) {
|
|
594
596
|
const text = fs.readFileSync(path.join(contractsDir, name), 'utf8');
|
|
595
|
-
|
|
597
|
+
|
|
598
|
+
// `contracts/` may also hold a README or notes: only files with a contract
|
|
599
|
+
// header are counted, and only a broken contract header is a failure.
|
|
600
|
+
if (!isContractText(text)) {
|
|
601
|
+
if (looksLikeContract(text)) unreadable.push(name);
|
|
602
|
+
else ignored.push(name);
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
contracts += 1;
|
|
596
607
|
if (/^\s*#.*\|\s*⏳\s*$/m.test(text)) stalled.push(name);
|
|
597
608
|
}
|
|
598
609
|
}
|
|
599
610
|
|
|
600
611
|
if (unreadable.length > 0) add('contratos', 'FAIL', `encabezado ilegible: ${unreadable.join(', ')}`);
|
|
601
|
-
else add('contratos', 'OK',
|
|
612
|
+
else add('contratos', 'OK', `${contracts} contrato(s) legibles${ignored.length ? ` · ignorados: ${ignored.join(', ')}` : ''}`);
|
|
602
613
|
|
|
603
614
|
if (stalled.length > 0) add('en curso', 'WARN', `ítems en ⏳ (reanudar): ${stalled.join(', ')}`);
|
|
604
615
|
else add('en curso', 'OK', 'sin ítems interrumpidos');
|
|
@@ -1320,6 +1331,7 @@ function commandReview() {
|
|
|
1320
1331
|
|
|
1321
1332
|
for (const file of fs.readdirSync(contractsDir).filter(name => name.toLowerCase().endsWith('.md'))) {
|
|
1322
1333
|
const text = fs.readFileSync(path.join(contractsDir, file), 'utf8');
|
|
1334
|
+
if (!isContractText(text)) continue;
|
|
1323
1335
|
const id = (text.match(/^#\s*ID:\s*(\S+)\s*$/m) || [])[1] || file.replace(/\.md$/, '');
|
|
1324
1336
|
const status = (text.match(/^#\s*Status:\s*(\w+)\s*$/m) || [])[1] || 'UNKNOWN';
|
|
1325
1337
|
const criteria = readCriteria(text);
|
package/mcp/server.js
CHANGED
|
@@ -327,12 +327,30 @@ function inferContractType(contractId, text, fileName) {
|
|
|
327
327
|
return 'feature';
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
// A contract is recognized by its header, not by its extension: `contracts/` may
|
|
331
|
+
// also hold a README or free-form notes that must be ignored.
|
|
332
|
+
function isContractText(text) {
|
|
333
|
+
return /^#\s*ID:/m.test(text) && /^#\s*Status:/m.test(text);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Files that *look* like contracts but cannot be read as one are real errors.
|
|
337
|
+
function looksLikeContract(text) {
|
|
338
|
+
return /^#\s*CONTRACT:/m.test(text);
|
|
339
|
+
}
|
|
340
|
+
|
|
330
341
|
function listContractFiles() {
|
|
331
342
|
if (!fs.existsSync(CONTRACTS_DIR)) return [];
|
|
332
343
|
return fs
|
|
333
344
|
.readdirSync(CONTRACTS_DIR, { withFileTypes: true })
|
|
334
345
|
.filter(entry => entry.isFile() && entry.name.toLowerCase().endsWith('.md'))
|
|
335
|
-
.map(entry => entry.name)
|
|
346
|
+
.map(entry => entry.name)
|
|
347
|
+
.filter(name => {
|
|
348
|
+
try {
|
|
349
|
+
return isContractText(fs.readFileSync(path.join(CONTRACTS_DIR, name), 'utf8'));
|
|
350
|
+
} catch (error) {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
});
|
|
336
354
|
}
|
|
337
355
|
|
|
338
356
|
// Finds a contract by ID regardless of the file naming convention
|
|
@@ -1483,7 +1501,7 @@ ${evidence}
|
|
|
1483
1501
|
|
|
1484
1502
|
case 'sdd_get_status': {
|
|
1485
1503
|
if (!fs.existsSync(CONTRACTS_DIR)) return { total_contracts: 0, contracts: [] };
|
|
1486
|
-
const files =
|
|
1504
|
+
const files = listContractFiles();
|
|
1487
1505
|
|
|
1488
1506
|
const summary = files.map(file => {
|
|
1489
1507
|
const content = fs.readFileSync(path.join(CONTRACTS_DIR, file), 'utf8');
|
|
@@ -1517,7 +1535,7 @@ ${evidence}
|
|
|
1517
1535
|
const response = { ...metrics, source };
|
|
1518
1536
|
if (warning) response.warning = warning;
|
|
1519
1537
|
if (fs.existsSync(CONTRACTS_DIR)) {
|
|
1520
|
-
response.total_contracts =
|
|
1538
|
+
response.total_contracts = listContractFiles().length;
|
|
1521
1539
|
} else {
|
|
1522
1540
|
response.total_contracts = 0;
|
|
1523
1541
|
}
|
|
@@ -1527,7 +1545,7 @@ ${evidence}
|
|
|
1527
1545
|
case 'sdd_audit_traceability': {
|
|
1528
1546
|
// BR-005: real coverage. Nothing here is a fixed value.
|
|
1529
1547
|
const contractFiles = fs.existsSync(CONTRACTS_DIR)
|
|
1530
|
-
?
|
|
1548
|
+
? listContractFiles()
|
|
1531
1549
|
: [];
|
|
1532
1550
|
|
|
1533
1551
|
const specs = [];
|
|
@@ -1665,7 +1683,7 @@ function main() {
|
|
|
1665
1683
|
});
|
|
1666
1684
|
}
|
|
1667
1685
|
|
|
1668
|
-
module.exports = { TOOLS, handleToolCall, computeNextContractId, reconcileContract, computeCriteriaHashes };
|
|
1686
|
+
module.exports = { TOOLS, handleToolCall, computeNextContractId, reconcileContract, computeCriteriaHashes, isContractText, looksLikeContract };
|
|
1669
1687
|
|
|
1670
1688
|
if (require.main === module) {
|
|
1671
1689
|
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sdd-gl",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Model Context Protocol (MCP) Server and CLI for Spec-Driven Development (SDD-GL)",
|
|
5
5
|
"main": "mcp/server.js",
|
|
6
6
|
"bin": {
|
|
@@ -35,8 +35,10 @@
|
|
|
35
35
|
"dashboard": "node mcp/dashboard-gen.js",
|
|
36
36
|
"dashboard:public": "node mcp/dashboard-gen.js --public",
|
|
37
37
|
"fixture": "node test-sandbox/fixtures/demo-project.js",
|
|
38
|
-
"test": "node test-sandbox/id-generation.test.js && node test-sandbox/step-loop.test.js && node test-sandbox/mcp-core.test.js && node test-sandbox/neutral-format.test.js && node test-sandbox/atomicity.test.js && node test-sandbox/metrics.test.js && node test-sandbox/usage.test.js && node test-sandbox/fix-0001-docs.test.js && node test-sandbox/ci-workflow.test.js && node test-sandbox/interop.test.js && node test-sandbox/cli.test.js && node test-sandbox/fixture-project.test.js && node test-sandbox/split.test.js && node test-sandbox/reconcile.test.js && node test-sandbox/review.test.js && node test-sandbox/publish.test.js && node test-sandbox/multilayer-verifier.test.js && node test-sandbox/escrow.test.js && node test-sandbox/mcp-client-e2e.js",
|
|
39
|
-
"prepublishOnly": "npm test"
|
|
38
|
+
"test": "node test-sandbox/id-generation.test.js && node test-sandbox/step-loop.test.js && node test-sandbox/mcp-core.test.js && node test-sandbox/neutral-format.test.js && node test-sandbox/atomicity.test.js && node test-sandbox/metrics.test.js && node test-sandbox/usage.test.js && node test-sandbox/fix-0001-docs.test.js && node test-sandbox/ci-workflow.test.js && node test-sandbox/interop.test.js && node test-sandbox/cli.test.js && node test-sandbox/fixture-project.test.js && node test-sandbox/split.test.js && node test-sandbox/reconcile.test.js && node test-sandbox/review.test.js && node test-sandbox/publish.test.js && node test-sandbox/doctor.test.js && node test-sandbox/orchestrator-docs.test.js && node test-sandbox/multilayer-verifier.test.js && node test-sandbox/escrow.test.js && node test-sandbox/mcp-client-e2e.js",
|
|
39
|
+
"prepublishOnly": "npm test && node scripts/release.js --check",
|
|
40
|
+
"release:check": "node scripts/release.js --check",
|
|
41
|
+
"release:prepare": "node scripts/release.js"
|
|
40
42
|
},
|
|
41
43
|
"keywords": [
|
|
42
44
|
"mcp",
|