From b305f29681d9b8edf885b37dce521615d6c49c81 Mon Sep 17 00:00:00 2001 From: "Cerebro IA v2.0" Date: Sun, 19 Jul 2026 17:28:48 -0500 Subject: [PATCH] =?UTF-8?q?Superficies=20multi-editor=20devSteps:=20plugin?= =?UTF-8?q?=20Claude=20Code,=20skill,=20.codex,=20opencode.json=20(fix=20k?= =?UTF-8?q?ey=20'project'),=20extensi=C3=B3n=20VS=20Code,=20INSTALL.=20Adi?= =?UTF-8?q?tivo.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- .claude-plugin/plugin.json | 42 +++ .claude/skills/orchestrate-lifecycle/SKILL.md | 73 +++++ .codex/config.toml | 8 + INSTALL_DEVSTEPS.md | 147 +++++++++ extension/.vscodeignore | 4 + extension/README.md | 38 +++ extension/extension.js | 304 ++++++++++++++++++ extension/media/devsteps.svg | 6 + extension/package.json | 83 +++++ opencode.json | 7 - 10 files changed, 705 insertions(+), 7 deletions(-) create mode 100644 .claude-plugin/plugin.json create mode 100644 .claude/skills/orchestrate-lifecycle/SKILL.md create mode 100644 .codex/config.toml create mode 100644 INSTALL_DEVSTEPS.md create mode 100644 extension/.vscodeignore create mode 100644 extension/README.md create mode 100644 extension/extension.js create mode 100644 extension/media/devsteps.svg create mode 100644 extension/package.json diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..0c3d973 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,42 @@ +{ + "name": "sp-devsteps", + "version": "1.0.0", + "description": "Orquesta proyectos con devSteps mediante CLI, skills de Claude Code y el MCP local de DevControl.", + "author": { + "name": "SolucionesPro" + }, + "license": "MIT", + "keywords": [ + "devsteps", + "lifecycle", + "pipeline", + "scaffolding", + "mcp", + "devcontrol" + ], + "skills": "./.claude/skills", + "mcpServers": { + "devcontrol": { + "type": "sse", + "url": "http://localhost:7893/mcp" + } + }, + "interface": { + "displayName": "SP-devSteps", + "shortDescription": "Pipeline, scaffolding y validacion DS-v1 para proyectos asistidos por agentes.", + "longDescription": "Guia el ciclo de vida de un proyecto con devSteps, genera contexto para agentes y usa DevControl como MCP de gobernanza cuando esta disponible.", + "developerName": "SolucionesPro", + "category": "Productivity", + "capabilities": [ + "Read", + "Analysis", + "Project Management" + ], + "defaultPrompt": [ + "Revisa el estado del pipeline devSteps.", + "Guia el siguiente paso del proyecto.", + "Valida el proyecto con DS-v1." + ], + "brandColor": "#2563EB" + } +} diff --git a/.claude/skills/orchestrate-lifecycle/SKILL.md b/.claude/skills/orchestrate-lifecycle/SKILL.md new file mode 100644 index 0000000..63ef08a --- /dev/null +++ b/.claude/skills/orchestrate-lifecycle/SKILL.md @@ -0,0 +1,73 @@ +--- +name: orchestrate-lifecycle +description: Guiar proyectos con devSteps usando el CLI, el pipeline, scaffolding, validaciones DS-v1 y el MCP de DevControl cuando este disponible. +--- + +# Orquestar ciclo de vida con devSteps + +Usar esta skill cuando el usuario pida iniciar, guiar, validar, revisar o avanzar un proyecto con devSteps. + +devSteps es el orquestador del pipeline. DevControl es la capa MCP de gobernanza declarada en `.mcp.json` como servidor `devcontrol`. + +## Flujo base + +1. Leer `devsteps.yaml`, `AGENTS.md` o `CLAUDE.md` si existen. +2. Ejecutar `devsteps status` para ubicar el paso actual antes de modificar archivos. +3. Si el proyecto no tiene `devsteps.yaml`, proponer o ejecutar scaffolding con `devsteps scaffold`. +4. Antes de implementar, identificar el paso del pipeline, criterios de entrada, criterios de salida y artefactos esperados. +5. Usar el CLI para operaciones de ciclo de vida: + - `devsteps guide` para guiar al usuario paso a paso. + - `devsteps run` para ejecutar el pipeline. + - `devsteps validate` para validar DS-v1. + - `devsteps step:complete ` para marcar pasos terminados cuando el usuario apruebe. + - `devsteps inject` para regenerar instrucciones de agentes cuando cambie el pipeline. +6. Usar el MCP `devcontrol` si esta conectado para gobierno, politicas, sesiones, aprobaciones o chequeos complementarios. +7. Si el MCP no esta disponible, continuar con el CLI de devSteps y documentar la limitacion. +8. No saltar aprobaciones humanas declaradas en el pipeline. +9. No fabricar artefactos de salida: crear solo los archivos exigidos por el paso activo o por la solicitud explicita. +10. Cerrar el trabajo con `devsteps validate` cuando el cambio toque documentacion, configuracion, fuente o tests. + +## Scaffolding + +Para crear una base nueva: + +```bash +devsteps scaffold --name "Mi Proyecto" --type web-app --stack typescript,node --force +devsteps inject +devsteps validate +``` + +Despues de scaffolding, revisar los archivos generados antes de modificar el codigo: + +- `devsteps.yaml` +- `README.md` +- `docs/requirements.md` +- `docs/architecture.md` +- `AGENTS.md` +- `CLAUDE.md` + +## MCP + +El MCP declarado por devSteps es: + +```json +{ + "mcpServers": { + "devcontrol": { + "type": "sse", + "url": "http://localhost:7893/mcp" + } + } +} +``` + +Antes de depender de herramientas MCP, verificar que el servidor local de DevControl este iniciado y accesible. Si no lo esta, pedir al usuario que lo inicie o trabajar solo con el CLI. + +## Cierre esperado + +Al finalizar una tarea: + +1. Resumir el paso de pipeline trabajado. +2. Listar archivos modificados. +3. Reportar validaciones ejecutadas. +4. Indicar si queda pendiente aprobacion humana del pipeline. diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 0000000..12dba77 --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,8 @@ +# devSteps orquesta el ciclo de vida del proyecto; la gobernanza (gates/aprobaciones) +# la aplica DevControl vía su MCP. El CLI de devSteps (sp-devsteps) se usa directamente. +[mcp_servers.devcontrol] +command = "sp-devcontrol" +args = ["mcp"] + +[mcp_servers.devcontrol.env] +DEVCONTROL_PROJECT_ROOT = "${CLAUDE_PROJECT_DIR:-.}" diff --git a/INSTALL_DEVSTEPS.md b/INSTALL_DEVSTEPS.md new file mode 100644 index 0000000..6f6627b --- /dev/null +++ b/INSTALL_DEVSTEPS.md @@ -0,0 +1,147 @@ +# Instalacion multi-editor de devSteps + +`SP-devSteps` es un modulo CLI-first. La integracion universal se hace mediante el MCP local declarado en `.mcp.json`; no existe una API HTTP publica propia de devSteps ni un OpenAPI para ChatGPT web. + +## Prerrequisitos + +- Node.js 20 o superior. +- `sp-devsteps` instalado o este repositorio construido localmente. +- Para MCP: servidor local de DevControl disponible en `http://localhost:7893/mcp`. + +Instalacion del CLI: + +```bash +npm install -g sp-devsteps +devsteps --help +``` + +Uso desde este repositorio: + +```bash +npm install +npm run build +npm link +devsteps --help +``` + +## Claude Code + +Claude Code puede usar dos superficies: + +- Skill: `.claude/skills/orchestrate-lifecycle/SKILL.md`. +- Plugin: `.claude-plugin/plugin.json`. + +El plugin declara el MCP: + +```json +{ + "mcpServers": { + "devcontrol": { + "type": "sse", + "url": "http://localhost:7893/mcp" + } + } +} +``` + +Flujo recomendado dentro del proyecto: + +```bash +devsteps inject +devsteps status +devsteps validate +``` + +Prompt inicial: + +```text +Usa la skill orchestrate-lifecycle. Lee CLAUDE.md y devsteps.yaml, revisa el estado del pipeline y dime el siguiente paso antes de modificar archivos. +``` + +## Codex + +Codex ya puede leer `AGENTS.md`. La configuracion esperada para `.codex/config.toml` es: + +```toml +[mcp_servers.devcontrol] +url = "http://localhost:7893/mcp" +``` + +Alternativa manual equivalente: + +```bash +codex mcp add devcontrol --url http://localhost:7893/mcp +``` + +Prompt inicial: + +```text +Lee AGENTS.md y devsteps.yaml. Usa devSteps para guiar el pipeline, valida con devsteps validate y usa el MCP devcontrol si esta conectado. +``` + +## OpenCode + +OpenCode usa `opencode.json`, ya incluido: + +```json +{ + "mcp": { + "devcontrol": { + "type": "remote", + "url": "http://localhost:7893/mcp", + "enabled": true + } + } +} +``` + +Uso recomendado: + +```bash +opencode . +``` + +Prompt inicial: + +```text +Lee AGENTS.md y devsteps.yaml. Revisa el estado del pipeline y recomienda el siguiente paso. +``` + +## ChatGPT + +devSteps es CLI-only. Para ChatGPT, la via soportada es ChatGPT Desktop con connector MCP apuntando al servidor local: + +- Nombre: `devcontrol` +- Tipo: SSE o remote MCP, segun el cliente +- URL: `http://localhost:7893/mcp` + +ChatGPT web con GPT Actions no aplica para devSteps porque no hay API HTTP propia que describir. No se provee `chatgpt/openapi.yaml`. + +## CLI directo + +Comandos principales: + +```bash +devsteps scaffold --name "Mi Proyecto" --type web-app --stack typescript,node --force +devsteps guide +devsteps run +devsteps status +devsteps validate +devsteps inject +devsteps step:complete +``` + +## Verificacion + +Antes de entregar cambios de integracion: + +```bash +node -e "JSON.parse(require('fs').readFileSync('.mcp.json','utf8')); JSON.parse(require('fs').readFileSync('.claude-plugin/plugin.json','utf8')); console.log('json ok')" +python3 - <<'PY' +import tomllib +tomllib.loads('[mcp_servers.devcontrol]\nurl = "http://localhost:7893/mcp"\n') +print('toml ok') +PY +test -f .mcp.json +devsteps validate +``` diff --git a/extension/.vscodeignore b/extension/.vscodeignore new file mode 100644 index 0000000..5fb4534 --- /dev/null +++ b/extension/.vscodeignore @@ -0,0 +1,4 @@ +node_modules/ +*.vsix +npm-debug.log + diff --git a/extension/README.md b/extension/README.md new file mode 100644 index 0000000..3b8a540 --- /dev/null +++ b/extension/README.md @@ -0,0 +1,38 @@ +# SP-devSteps Editor Extension + +Extensión VSIX para usar `devsteps` desde una pestaña dentro de VS Code, Cursor o Windsurf. + +## Prerrequisitos + +- Node.js 20 o superior. +- `devsteps` instalado globalmente, o este repositorio construido con `npm run build`. +- Para MCP, DevControl escuchando en `http://localhost:7893/mcp`. + +## Empaquetar + +```bash +cd extension +npm install +npx @vscode/vsce package +``` + +El comando genera un `.vsix` instalable con: + +```bash +code --install-extension sp-devsteps-editor-1.0.0.vsix +``` + +Cursor y Windsurf aceptan el mismo paquete VSIX desde su instalador de extensiones compatible con VS Code. + +## Panel + +El contenedor `devSteps` aparece en la Activity Bar y expone comandos para: + +- `devsteps status` +- `devsteps validate` +- `devsteps inject` +- `devsteps run` +- registrar `.mcp.json` con el MCP local de DevControl usado por devSteps. + +La extensión no reimplementa la lógica del módulo; invoca el CLI y conserva MCP como integración universal. + diff --git a/extension/extension.js b/extension/extension.js new file mode 100644 index 0000000..b88f99a --- /dev/null +++ b/extension/extension.js @@ -0,0 +1,304 @@ +const vscode = require('vscode') +const fs = require('fs') +const path = require('path') +const { spawn } = require('child_process') + +const VIEW_ID = 'devsteps.controlPanel' + +function activate(context) { + const output = vscode.window.createOutputChannel('devSteps') + const provider = new DevStepsViewProvider(context.extensionUri, output) + + context.subscriptions.push( + output, + vscode.window.registerWebviewViewProvider(VIEW_ID, provider), + vscode.commands.registerCommand('devsteps.status', () => provider.runCliCommand(['status'])), + vscode.commands.registerCommand('devsteps.validate', () => provider.runCliCommand(['validate'])), + vscode.commands.registerCommand('devsteps.run', () => provider.runCliCommand(['run'])), + vscode.commands.registerCommand('devsteps.inject', () => provider.runCliCommand(['inject'])), + vscode.commands.registerCommand('devsteps.registerMcp', () => provider.registerMcp()), + vscode.commands.registerCommand('devsteps.openTerminal', () => openDevStepsTerminal()) + ) +} + +function deactivate() {} + +class DevStepsViewProvider { + constructor(extensionUri, output) { + this.extensionUri = extensionUri + this.output = output + this.view = undefined + } + + resolveWebviewView(webviewView) { + this.view = webviewView + webviewView.webview.options = { + enableScripts: true, + localResourceRoots: [this.extensionUri], + } + webviewView.webview.html = this.render(webviewView.webview) + webviewView.webview.onDidReceiveMessage((message) => { + if (!message || typeof message.command !== 'string') return + if (message.command === 'registerMcp') { + void this.registerMcp() + return + } + const allowed = new Map([ + ['status', ['status']], + ['validate', ['validate']], + ['inject', ['inject']], + ['run', ['run']], + ]) + const args = allowed.get(message.command) + if (args) void this.runCliCommand(args) + }) + } + + async runCliCommand(args) { + const workspaceRoot = getWorkspaceRoot() + if (!workspaceRoot) { + void vscode.window.showWarningMessage('Abre una carpeta de proyecto para ejecutar devSteps.') + this.postResult('Sin carpeta abierta.') + return + } + + const cli = resolveCli(workspaceRoot) + const title = `devsteps ${args.join(' ')}` + this.output.appendLine(`$ ${title}`) + this.postResult(`Ejecutando: ${title}`) + + try { + const result = await runProcess(cli.command, [...cli.args, ...args], workspaceRoot) + const text = result.stdout || result.stderr || 'Comando finalizado sin salida.' + this.output.appendLine(text) + this.postResult(text) + } catch (error) { + const detail = error instanceof Error ? error.message : String(error) + this.output.appendLine(detail) + this.postResult(detail) + void vscode.window.showErrorMessage(`devSteps fallo: ${detail}`) + } + } + + async registerMcp() { + const workspaceRoot = getWorkspaceRoot() + if (!workspaceRoot) { + void vscode.window.showWarningMessage('Abre una carpeta de proyecto para registrar MCP.') + this.postResult('Sin carpeta abierta.') + return + } + + const mcpPath = path.join(workspaceRoot, '.mcp.json') + const current = readJsonFile(mcpPath) || {} + const mcpServers = current.mcpServers && typeof current.mcpServers === 'object' + ? current.mcpServers + : {} + + const next = { + ...current, + mcpServers: { + ...mcpServers, + devcontrol: { + type: 'sse', + url: 'http://localhost:7893/mcp', + }, + }, + } + + fs.writeFileSync(mcpPath, `${JSON.stringify(next, null, 2)}\n`) + this.postResult('MCP registrado en .mcp.json.') + void vscode.window.showInformationMessage('devSteps MCP registrado en .mcp.json.') + + const document = await vscode.workspace.openTextDocument(mcpPath) + await vscode.window.showTextDocument(document, { preview: false }) + } + + postResult(text) { + if (!this.view) return + this.view.webview.postMessage({ type: 'result', text }) + } + + render(webview) { + const nonce = getNonce() + return ` + + + + + + devSteps + + + +

SP-devSteps

+
+ + + + + +
+
Listo
+

+  
+
+`
+  }
+}
+
+function getWorkspaceRoot() {
+  const folders = vscode.workspace.workspaceFolders
+  return folders && folders.length > 0 ? folders[0].uri.fsPath : undefined
+}
+
+function resolveCli(workspaceRoot) {
+  const localDist = path.join(workspaceRoot, 'dist', 'cli.js')
+  if (fs.existsSync(localDist)) {
+    return { command: process.execPath, args: [localDist] }
+  }
+
+  const binName = process.platform === 'win32' ? 'devsteps.cmd' : 'devsteps'
+  const localBin = path.join(workspaceRoot, 'node_modules', '.bin', binName)
+  if (fs.existsSync(localBin)) {
+    return { command: localBin, args: [] }
+  }
+
+  return { command: binName, args: [] }
+}
+
+function runProcess(command, args, cwd) {
+  return new Promise((resolve, reject) => {
+    const child = spawn(command, args, {
+      cwd,
+      shell: process.platform === 'win32',
+      env: process.env,
+    })
+    let stdout = ''
+    let stderr = ''
+    child.stdout.on('data', (chunk) => {
+      stdout += chunk.toString()
+    })
+    child.stderr.on('data', (chunk) => {
+      stderr += chunk.toString()
+    })
+    child.on('error', reject)
+    child.on('close', (code) => {
+      if (code === 0) {
+        resolve({ stdout, stderr })
+        return
+      }
+      reject(new Error((stderr || stdout || `Comando finalizo con codigo ${code}`).trim()))
+    })
+  })
+}
+
+function readJsonFile(filePath) {
+  if (!fs.existsSync(filePath)) return undefined
+  try {
+    return JSON.parse(fs.readFileSync(filePath, 'utf8'))
+  } catch {
+    return undefined
+  }
+}
+
+function openDevStepsTerminal() {
+  const workspaceRoot = getWorkspaceRoot()
+  const terminal = vscode.window.createTerminal({
+    name: 'devSteps',
+    cwd: workspaceRoot,
+  })
+  terminal.show()
+  terminal.sendText('devsteps --help')
+}
+
+function getNonce() {
+  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+  let nonce = ''
+  for (let i = 0; i < 32; i += 1) {
+    nonce += chars.charAt(Math.floor(Math.random() * chars.length))
+  }
+  return nonce
+}
+
+module.exports = {
+  activate,
+  deactivate,
+}
+
diff --git a/extension/media/devsteps.svg b/extension/media/devsteps.svg
new file mode 100644
index 0000000..cf5673e
--- /dev/null
+++ b/extension/media/devsteps.svg
@@ -0,0 +1,6 @@
+
+  
+  
+  
+
+
diff --git a/extension/package.json b/extension/package.json
new file mode 100644
index 0000000..6d5c04d
--- /dev/null
+++ b/extension/package.json
@@ -0,0 +1,83 @@
+{
+  "name": "sp-devsteps-editor",
+  "displayName": "SP-devSteps",
+  "description": "Panel de control de devSteps para VS Code, Cursor y Windsurf.",
+  "version": "1.0.0",
+  "publisher": "solucionespro",
+  "license": "MIT",
+  "engines": {
+    "vscode": "^1.90.0"
+  },
+  "categories": [
+    "Other"
+  ],
+  "main": "./extension.js",
+  "activationEvents": [
+    "onView:devsteps.controlPanel",
+    "onCommand:devsteps.status",
+    "onCommand:devsteps.validate",
+    "onCommand:devsteps.run",
+    "onCommand:devsteps.inject",
+    "onCommand:devsteps.registerMcp",
+    "onCommand:devsteps.openTerminal"
+  ],
+  "contributes": {
+    "viewsContainers": {
+      "activitybar": [
+        {
+          "id": "devsteps",
+          "title": "devSteps",
+          "icon": "media/devsteps.svg"
+        }
+      ]
+    },
+    "views": {
+      "devsteps": [
+        {
+          "id": "devsteps.controlPanel",
+          "name": "Panel"
+        }
+      ]
+    },
+    "commands": [
+      {
+        "command": "devsteps.status",
+        "title": "devSteps: Estado",
+        "category": "devSteps"
+      },
+      {
+        "command": "devsteps.validate",
+        "title": "devSteps: Validar",
+        "category": "devSteps"
+      },
+      {
+        "command": "devsteps.run",
+        "title": "devSteps: Ejecutar Pipeline",
+        "category": "devSteps"
+      },
+      {
+        "command": "devsteps.inject",
+        "title": "devSteps: Inyectar Agentes",
+        "category": "devSteps"
+      },
+      {
+        "command": "devsteps.registerMcp",
+        "title": "devSteps: Registrar MCP",
+        "category": "devSteps"
+      },
+      {
+        "command": "devsteps.openTerminal",
+        "title": "devSteps: Abrir Terminal",
+        "category": "devSteps"
+      }
+    ]
+  },
+  "scripts": {
+    "package": "vsce package",
+    "validate": "node -e \"JSON.parse(require('fs').readFileSync('package.json','utf8')); console.log('extension package.json ok')\""
+  },
+  "devDependencies": {
+    "@vscode/vsce": "^3.2.0"
+  }
+}
+
diff --git a/opencode.json b/opencode.json
index 445070d..7345bb4 100644
--- a/opencode.json
+++ b/opencode.json
@@ -6,12 +6,5 @@
       "url": "http://localhost:7893/mcp",
       "enabled": true
     }
-  },
-  "project": {
-    "family": "SolucionesPro Agentic Stack",
-    "siblingTools": [
-      "sp-devsteps",
-      "sp-devcontrol"
-    ]
   }
 }