kdd-scaffold
No description
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 27, 2026
- Updated
- Aug 27, 2026
Introduction
kdd-scaffold
Plugin de composición para DeepSeek Harness (dsh) que expone una Tool para generar un contrato de tarea KDD nuevo: kdd_scaffold.
Complementa a kdd-gates — ese valida contratos, este los genera. No reimplementa la metodología: produce exactamente el mismo formato que knowledge/contracts/TEMPLATE-task-contract.md de la plantilla KDD.
Requisito
El repo destino (repoRoot) tiene que tener la plantilla KDD instalada (scripts/, knowledge/). El archivo de tests del oráculo (testsPath) tiene que existir ya cuando se llama a la tool — es oracle-first: se escribe el test antes que el contrato, nunca al revés.
Instalación
-
Dependencias locales:
cd kdd-scaffold npm install -
Montarlo en el perfil de
dsh(~/.dsh/profiles/<perfil>/cordis.patch.yml):- insert: - id: kdd-scaffold name: 'file:///C:/ruta/a/kdd-scaffold/host.js' -
Reiniciar el proceso de
dshpara que cargue el plugin.
Tool
kdd_scaffold
Genera knowledge/contracts/<task>.md completo (frontmatter + las 7 secciones obligatorias). Nunca sobreescribe un contrato existente.
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
repoRoot | string | sí | Ruta absoluta del repo KDD. |
task | string | sí | Nombre kebab-case — define el archivo knowledge/contracts/<task>.md. |
title | string | sí | |
description | string | sí | Una frase. |
intent | string | sí | UNA frase, UN verbo — va al frontmatter. |
intentBody | string | no | 2-4 líneas para el cuerpo de ## Intent. Default: reusa intent. |
target | string | sí | Ruta repo-relativa donde vivirá la implementación. |
signature | string | sí | Firma completa, ej. "def f(x: int) -> str:". |
testCommand | string | sí | Comando que corre SOLO los tests de esta tarea. |
testsPath | string | sí | Ruta repo-relativa al archivo de tests del oráculo. Debe existir ya. |
tags | array<string> | sí | Al menos un tag, se pasa a minúsculas automáticamente. |
cyclomaticMax / nestingMax / linesMax / paramsMax | integer | no | Presupuesto de complejidad. Default: cyclomatic_max: 8, nesting_max: 3. |
touchOnly | array<string> | no | Default: [target]. |
depsAllowed | array<string> | no | Default: []. |
forbids | array<string> | no | Default: [network, subprocess, llm]. |
invariants / examples / doList / dontList | array<string> | no | Placeholders <TODO: ...> si se omiten. examples necesita ≥2 items — si se pasan menos, se completa con placeholders hasta 2. |
Devuelve { ok, path, testsSha256, reason? }.
Decisiones de diseño (por qué está armado así)
- Escribe vía
ctx.fs, nonode:fsdirecto. Un tool de plugin que muta archivos puede usar Node sin restricciones, pero eso evita el sandbox/observed-state pipeline del harness — la misma tool oficial (dsh-tool-str-replace-editor) usactx.fs.resolve/stat/readText/writeTextconctx.waterfall('fs/write-intent', ...)yctx.emit('fs/observed', ...);kdd_scaffoldsigue el mismo patrón para que sus escrituras queden visibles igual que una edición normal del agente. tests_sha256lo calcula el propio plugin, nunca un valor pasado por el llamador. Lee el archivo real, normaliza newlines a LF y aplica SHA256 — el mismo algoritmo exacto descripts/validate_contracts.py --hash. Confiar en un hash externo rompería el sentido de congelar el oráculo.tagses requerido, no opcional con default[]. Encontrado en vivo: untags: []pasavalidate_contracts.pysin problema, perovalidate_okf.py(que también escaneaknowledge/contracts/) exige una lista no vacía y en minúsculas — sin este fix, todo contrato generado pasaba Nivel 1 "core" pero fallaba el gate OKF.- Sin escapado de comillas internas en los valores del frontmatter. El parser YAML de
validate_contracts.py(_parse_scalar) es un subconjunto hecho a mano: solo pela un par de comillas externas coincidentes, no interpreta\"ni''como escapes. Escapar hubiera insertado el caracter de escape literal en el valor — los valores se insertan crudos, igual que enTEMPLATE-task-contract.md. - Nunca sobreescribe. Si
knowledge/contracts/<task>.mdya existe, falla con un mensaje explícito — evita perder ediciones manuales de un contrato por un nombre de tarea repetido. - No crea el stub del
target. La plantilla lo pide como paso aparte (## Interfaceen la sección "COMO USAR" deTEMPLATE-task-contract.md) — generar el archivo de implementación es trabajo del agente, no de un tool de andamiaje del contrato.
Estado verificado
kdd_scaffoldseguido dekdd_validate(dekdd-gates), contra el repo KDD real: contrato generado pasóvalidate_contractsyvalidate_okfcon 0 errores en el primer intento (después del fix detags).