@trycore/spec-build-harness 0.1.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/.claude-plugin/marketplace.json +21 -0
- package/.claude-plugin/plugin.json +28 -0
- package/GOVERNANCE.md +48 -0
- package/INSTALL.md +295 -0
- package/METODOLOGIA.md +360 -0
- package/README.md +130 -0
- package/VERSION +1 -0
- package/agents/build/api-contract-tester.md +32 -0
- package/agents/build/build-orchestrator.md +50 -0
- package/agents/build/change-epic-coherence.md +41 -0
- package/agents/build/coherence-three-way.md +35 -0
- package/agents/build/data-consistency-checker.md +48 -0
- package/agents/build/dor-dod-gatekeeper.md +46 -0
- package/agents/build/security-reviewer.md +46 -0
- package/agents/build/simple-design-reviewer.md +33 -0
- package/agents/build/stack-guardian.md +41 -0
- package/agents/build/ux-krug-reviewer.md +33 -0
- package/commands/build/onboard.md +136 -0
- package/commands/opsx/apply.md +152 -0
- package/commands/opsx/archive.md +157 -0
- package/commands/opsx/bulk-archive.md +242 -0
- package/commands/opsx/continue.md +114 -0
- package/commands/opsx/explore.md +174 -0
- package/commands/opsx/ff.md +94 -0
- package/commands/opsx/new.md +69 -0
- package/commands/opsx/onboard.md +525 -0
- package/commands/opsx/sync.md +134 -0
- package/commands/opsx/verify.md +164 -0
- package/config/stack-allowlist.template.json +12 -0
- package/dist/cli.js +105 -0
- package/dist/commands/doctor.js +77 -0
- package/dist/commands/init.js +129 -0
- package/dist/commands/status.js +59 -0
- package/dist/commands/uninstall.js +52 -0
- package/dist/commands/update.js +11 -0
- package/dist/lib/install-engine.js +99 -0
- package/dist/lib/markers.js +81 -0
- package/dist/lib/paths.js +65 -0
- package/dist/lib/settings-merge.js +125 -0
- package/dist/lib/stack-prompt.js +69 -0
- package/dist/lib/state-seed.js +59 -0
- package/docs/agents.md +133 -0
- package/docs/commands.md +128 -0
- package/docs/customization/mcp-extensions.md +117 -0
- package/docs/examples/reference/data-consistency.example.md +61 -0
- package/docs/examples/reference/security-foco.example.md +39 -0
- package/docs/examples/reference/stack-allowlist.example.json +61 -0
- package/docs/getting-started.md +260 -0
- package/docs/hooks.md +143 -0
- package/hooks/build/build-gate-check.sh +24 -0
- package/hooks/build/coherence-flag.sh +23 -0
- package/hooks/build/gitflow-guard.sh +65 -0
- package/hooks/build/lint-typecheck.sh +33 -0
- package/hooks/build/load-build-state.sh +46 -0
- package/hooks/build/stack-guard.sh +63 -0
- package/hooks/build-harness.json +61 -0
- package/internal/skills/auditar-arnes/SKILL.md +29 -0
- package/package.json +67 -0
- package/scripts/check-agnostic.sh +81 -0
- package/scripts/check-state-clean.sh +48 -0
- package/scripts/check-version-sync.sh +51 -0
- package/scripts/denylist.txt +30 -0
- package/skills/building-a-slice/SKILL.md +82 -0
- package/skills/building-a-slice/references/data-consistency.md +34 -0
- package/skills/building-a-slice/references/dod.md +25 -0
- package/skills/building-a-slice/references/dor.md +17 -0
- package/skills/building-a-slice/references/gitflow.md +30 -0
- package/skills/building-a-slice/references/krug-ux.md +27 -0
- package/skills/building-a-slice/references/link-change-epic.md +34 -0
- package/skills/building-a-slice/references/mcp-map.md +29 -0
- package/skills/building-a-slice/references/newman-tests.md +47 -0
- package/skills/building-a-slice/references/simple-design.md +33 -0
- package/skills/building-a-slice/references/state-protocol.md +48 -0
- package/skills/openspec-apply-change/SKILL.md +156 -0
- package/skills/openspec-archive-change/SKILL.md +114 -0
- package/skills/openspec-bulk-archive-change/SKILL.md +246 -0
- package/skills/openspec-continue-change/SKILL.md +118 -0
- package/skills/openspec-explore/SKILL.md +290 -0
- package/skills/openspec-ff-change/SKILL.md +101 -0
- package/skills/openspec-new-change/SKILL.md +74 -0
- package/skills/openspec-onboard/SKILL.md +529 -0
- package/skills/openspec-sync-specs/SKILL.md +138 -0
- package/skills/openspec-verify-change/SKILL.md +168 -0
- package/skills/releasing-a-version/SKILL.md +56 -0
- package/skills/releasing-a-version/references/release-dod.md +20 -0
- package/state/README.md +56 -0
- package/state/build-state.schema.json +111 -0
- package/state/build-state.template.json +7 -0
- package/templates/CLAUDE.md.template +57 -0
- package/templates/newman.collection.template.json +28 -0
- package/templates/settings-hooks.template.json +25 -0
- package/templates/waivers/WAIVER.template.md +27 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "startup|clear|compact",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/load-build-state.sh\""
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"PreToolUse": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "Bash",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/gitflow-guard.sh\""
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
26
|
+
"hooks": [
|
|
27
|
+
{
|
|
28
|
+
"type": "command",
|
|
29
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/stack-guard.sh\""
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"PostToolUse": [
|
|
35
|
+
{
|
|
36
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
37
|
+
"hooks": [
|
|
38
|
+
{
|
|
39
|
+
"type": "command",
|
|
40
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/lint-typecheck.sh\""
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/coherence-flag.sh\""
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"Stop": [
|
|
50
|
+
{
|
|
51
|
+
"matcher": ".*",
|
|
52
|
+
"hooks": [
|
|
53
|
+
{
|
|
54
|
+
"type": "command",
|
|
55
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR/.claude}/hooks/build/build-gate-check.sh\""
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: auditar-arnes
|
|
3
|
+
description: Skill INTERNA (no se distribuye al consumidor). Audita el propio paquete del arnés cada 3-6 meses — poda de instrucciones obsoletas, validación de herramientas nativas que vuelvan redundante un hook/agente, re-sincronización de convenciones (schema ↔ agentes ↔ skills), y verificación de agnosticismo. Equivale a la cadencia de GOVERNANCE.md.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Auditar el arnés de construcción (mantenimiento del paquete)
|
|
7
|
+
|
|
8
|
+
Skill de **mantenedor**, no de consumidor. Vive en `internal/skills/` y se incluye en el
|
|
9
|
+
paquete npm (`files[]`) pero **NO** la instala el CLI ni la expone el plugin — solo se usa
|
|
10
|
+
trabajando sobre el repo del propio paquete.
|
|
11
|
+
|
|
12
|
+
## Cadencia (cada 3-6 meses)
|
|
13
|
+
|
|
14
|
+
1. **Poda de instrucciones**: borrar reglas que el modelo nuevo ya maneja nativamente
|
|
15
|
+
(las instrucciones obsoletas limitan a modelos más capaces). Revisar agentes y references.
|
|
16
|
+
2. **Validación de herramientas**: ¿hay modos nativos (LSP, MCP nuevos) que vuelvan redundante
|
|
17
|
+
un hook o un agente? Si sí, retirarlo.
|
|
18
|
+
3. **Coherencia de convenciones**: que `state/build-state.schema.json`, los agentes y las skills
|
|
19
|
+
sigan alineados (mismos nombres de gate/fase).
|
|
20
|
+
4. **Agnosticismo**: correr `bash scripts/check-agnostic.sh` y `bash scripts/check-state-clean.sh`;
|
|
21
|
+
confirmar que `docs/examples/` sigue siendo el único lugar con vocabulario de dominio.
|
|
22
|
+
5. **Sincronía de versión**: `bash scripts/check-version-sync.sh` (VERSION / package.json / plugin.json).
|
|
23
|
+
|
|
24
|
+
## Procedimiento
|
|
25
|
+
|
|
26
|
+
- Trabaja en rama (`chore/auditoria-arnes-YYYY-MM`), PR al cierre (el arnés se gobierna a sí mismo).
|
|
27
|
+
- Registra decisiones de poda/cambio en `GOVERNANCE.md` (bitácora).
|
|
28
|
+
- Si cambias el schema de estado, los nombres de gate/fase o la política de hooks, actualiza
|
|
29
|
+
en bloque agentes + skills + schema para no fragmentar convenciones.
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@trycore/spec-build-harness",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Arnés agéntico de construcción de Trycore para Claude Code: pipeline de dos loops (slice por épica + release gate) con gates de calidad, estado compartido y OpenSpec. Compañero de @trycore/spec-product-flow. Agnóstico al proyecto.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"trycore-build": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/",
|
|
11
|
+
".claude-plugin/",
|
|
12
|
+
"agents/",
|
|
13
|
+
"commands/",
|
|
14
|
+
"skills/",
|
|
15
|
+
"hooks/",
|
|
16
|
+
"config/",
|
|
17
|
+
"state/",
|
|
18
|
+
"templates/",
|
|
19
|
+
"internal/",
|
|
20
|
+
"docs/",
|
|
21
|
+
"scripts/",
|
|
22
|
+
"METODOLOGIA.md",
|
|
23
|
+
"GOVERNANCE.md",
|
|
24
|
+
"VERSION",
|
|
25
|
+
"README.md",
|
|
26
|
+
"INSTALL.md"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"prepublishOnly": "npm run build && bash scripts/check-version-sync.sh && bash scripts/check-agnostic.sh && bash scripts/check-state-clean.sh",
|
|
34
|
+
"test:smoke": "bash scripts/smoke-test.sh"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"claude-code",
|
|
38
|
+
"build-harness",
|
|
39
|
+
"openspec",
|
|
40
|
+
"tdd",
|
|
41
|
+
"gitflow",
|
|
42
|
+
"quality-gates",
|
|
43
|
+
"release-gate",
|
|
44
|
+
"agentic",
|
|
45
|
+
"two-loop",
|
|
46
|
+
"trycore"
|
|
47
|
+
],
|
|
48
|
+
"homepage": "https://github.com/trycore-co/trycore-spec-build-harness",
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/trycore-co/trycore-spec-build-harness.git"
|
|
52
|
+
},
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/trycore-co/trycore-spec-build-harness/issues"
|
|
55
|
+
},
|
|
56
|
+
"license": "UNLICENSED",
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"commander": "^12.1.0"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@types/node": "^20.14.0",
|
|
65
|
+
"typescript": "^5.5.0"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-agnostic.sh — guardia anti-contaminación del build harness.
|
|
3
|
+
# Verifica que el contenido distribuido NO mencione dominios de cliente ni el dominio KYC.
|
|
4
|
+
# IMPORTANTE: docs/examples/ está EXCLUIDO a propósito — ahí viven los ejemplos KYC legítimos.
|
|
5
|
+
#
|
|
6
|
+
# Salida 0 si limpio, 1 si encuentra violaciones. Corre en prepublishOnly.
|
|
7
|
+
|
|
8
|
+
set -uo pipefail
|
|
9
|
+
|
|
10
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
11
|
+
DENYLIST="$REPO_ROOT/scripts/denylist.txt"
|
|
12
|
+
|
|
13
|
+
if [[ ! -f "$DENYLIST" ]]; then
|
|
14
|
+
echo "✗ No se encuentra denylist en $DENYLIST" >&2
|
|
15
|
+
exit 2
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Patrón regex con word boundaries desde la denylist (evita falsos positivos por substring).
|
|
19
|
+
PATTERN=""
|
|
20
|
+
while IFS= read -r line; do
|
|
21
|
+
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
|
22
|
+
esc=$(printf '%s' "$line" | sed 's/[][\/.^$*+?(){}|]/\\&/g')
|
|
23
|
+
if [[ -z "$PATTERN" ]]; then
|
|
24
|
+
PATTERN="\\b${esc}\\b"
|
|
25
|
+
else
|
|
26
|
+
PATTERN="${PATTERN}|\\b${esc}\\b"
|
|
27
|
+
fi
|
|
28
|
+
done < "$DENYLIST"
|
|
29
|
+
|
|
30
|
+
if [[ -z "$PATTERN" ]]; then
|
|
31
|
+
echo "ℹ denylist vacía, nada que verificar."
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
echo "▶ check-agnostic: buscando menciones de clientes / dominio KYC en el contenido distribuido…"
|
|
36
|
+
echo " (docs/examples/ excluido a propósito — pack de ejemplos)"
|
|
37
|
+
echo ""
|
|
38
|
+
|
|
39
|
+
VIOLATIONS=()
|
|
40
|
+
|
|
41
|
+
# Solo lo que DEBE quedar agnóstico. NO incluye docs/examples/ (pack KYC legítimo).
|
|
42
|
+
TARGETS=(
|
|
43
|
+
"$REPO_ROOT/agents"
|
|
44
|
+
"$REPO_ROOT/commands"
|
|
45
|
+
"$REPO_ROOT/skills"
|
|
46
|
+
"$REPO_ROOT/hooks"
|
|
47
|
+
"$REPO_ROOT/config"
|
|
48
|
+
"$REPO_ROOT/state"
|
|
49
|
+
"$REPO_ROOT/templates"
|
|
50
|
+
"$REPO_ROOT/internal"
|
|
51
|
+
"$REPO_ROOT/docs/customization"
|
|
52
|
+
"$REPO_ROOT/METODOLOGIA.md"
|
|
53
|
+
"$REPO_ROOT/README.md"
|
|
54
|
+
"$REPO_ROOT/INSTALL.md"
|
|
55
|
+
"$REPO_ROOT/GOVERNANCE.md"
|
|
56
|
+
"$REPO_ROOT/.claude-plugin"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
for target in "${TARGETS[@]}"; do
|
|
60
|
+
[[ -e "$target" ]] || continue
|
|
61
|
+
hits=$(grep -riEn -- "$PATTERN" "$target" 2>/dev/null \
|
|
62
|
+
--include='*.md' --include='*.json' --include='*.sh' \
|
|
63
|
+
--exclude-dir='node_modules' || true)
|
|
64
|
+
if [[ -n "$hits" ]]; then
|
|
65
|
+
VIOLATIONS+=("$hits")
|
|
66
|
+
fi
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
if [[ ${#VIOLATIONS[@]} -eq 0 ]]; then
|
|
70
|
+
echo "✓ Contenido limpio. Cero menciones de clientes / dominio KYC."
|
|
71
|
+
exit 0
|
|
72
|
+
else
|
|
73
|
+
echo "✗ Violaciones detectadas:"
|
|
74
|
+
echo ""
|
|
75
|
+
for v in "${VIOLATIONS[@]}"; do
|
|
76
|
+
echo "$v"
|
|
77
|
+
done
|
|
78
|
+
echo ""
|
|
79
|
+
echo "Generaliza el contenido (o mueve el ejemplo concreto a docs/examples/) antes de publicar."
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-state-clean.sh — impide filtrar estado vivo de cliente en la publicación [C1].
|
|
3
|
+
# Falla (exit 1) si:
|
|
4
|
+
# - existe state/build-state.json (estado vivo) o state/newman-*.json en el repo del paquete
|
|
5
|
+
# - existe algún waiver concreto (waivers/*.md que no sea template)
|
|
6
|
+
# - build-state.template.json trae history[]/releases[] NO vacíos
|
|
7
|
+
# Corre en prepublishOnly.
|
|
8
|
+
|
|
9
|
+
set -uo pipefail
|
|
10
|
+
|
|
11
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
12
|
+
FAIL=0
|
|
13
|
+
|
|
14
|
+
# 1) Estado vivo no debe existir en el paquete
|
|
15
|
+
for f in "$REPO_ROOT/state/build-state.json"; do
|
|
16
|
+
if [[ -f "$f" ]]; then
|
|
17
|
+
echo "✗ Estado vivo presente en el paquete: $f (debe ser solo build-state.template.json)" >&2
|
|
18
|
+
FAIL=1
|
|
19
|
+
fi
|
|
20
|
+
done
|
|
21
|
+
if compgen -G "$REPO_ROOT/state/newman-*.json" > /dev/null; then
|
|
22
|
+
echo "✗ Artefacto de test vivo presente: state/newman-*.json" >&2
|
|
23
|
+
FAIL=1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# 2) Waivers concretos (solo se distribuye el template bajo templates/waivers/)
|
|
27
|
+
if [[ -d "$REPO_ROOT/waivers" ]]; then
|
|
28
|
+
echo "✗ Carpeta waivers/ con contenido de cliente presente (usa templates/waivers/WAIVER.template.md)" >&2
|
|
29
|
+
FAIL=1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# 3) El template de estado debe nacer VACÍO
|
|
33
|
+
TMPL="$REPO_ROOT/state/build-state.template.json"
|
|
34
|
+
if [[ -f "$TMPL" ]] && command -v node >/dev/null 2>&1; then
|
|
35
|
+
EMPTY=$(node -e "const s=require('$TMPL'); process.stdout.write(String((s.history||[]).length===0 && (s.releases||[]).length===0 && !s.active_slice))" 2>/dev/null)
|
|
36
|
+
if [[ "$EMPTY" != "true" ]]; then
|
|
37
|
+
echo "✗ state/build-state.template.json no está vacío (history/releases/active_slice deben venir vacíos)" >&2
|
|
38
|
+
FAIL=1
|
|
39
|
+
fi
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
if [[ "$FAIL" -eq 0 ]]; then
|
|
43
|
+
echo "✓ Sin estado vivo en el paquete. Listo para publicar."
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
echo "" >&2
|
|
47
|
+
echo "✗ check-state-clean: corrige lo anterior antes de publicar." >&2
|
|
48
|
+
exit 1
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-version-sync.sh — valida que las 3 fuentes de versión coincidan.
|
|
3
|
+
#
|
|
4
|
+
# Fuentes auditadas:
|
|
5
|
+
# - VERSION
|
|
6
|
+
# - package.json#version
|
|
7
|
+
# - .claude-plugin/plugin.json#version
|
|
8
|
+
#
|
|
9
|
+
# Salida 0 si las 3 son iguales, 1 si hay drift.
|
|
10
|
+
# Se ejecuta automáticamente vía `npm run prepublishOnly`.
|
|
11
|
+
# Uso manual: bash scripts/check-version-sync.sh
|
|
12
|
+
|
|
13
|
+
set -uo pipefail
|
|
14
|
+
|
|
15
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
16
|
+
|
|
17
|
+
VERSION_FILE="$REPO_ROOT/VERSION"
|
|
18
|
+
PKG_FILE="$REPO_ROOT/package.json"
|
|
19
|
+
PLUGIN_FILE="$REPO_ROOT/.claude-plugin/plugin.json"
|
|
20
|
+
|
|
21
|
+
# Verificación de existencia
|
|
22
|
+
for f in "$VERSION_FILE" "$PKG_FILE" "$PLUGIN_FILE"; do
|
|
23
|
+
if [ ! -f "$f" ]; then
|
|
24
|
+
echo "✗ No se encuentra: $f" >&2
|
|
25
|
+
exit 2
|
|
26
|
+
fi
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
V_FILE=$(tr -d '[:space:]' < "$VERSION_FILE")
|
|
30
|
+
V_PKG=$(node -e "console.log(require('$PKG_FILE').version)" 2>/dev/null)
|
|
31
|
+
V_PLUGIN=$(node -e "console.log(require('$PLUGIN_FILE').version)" 2>/dev/null)
|
|
32
|
+
|
|
33
|
+
if [ -z "$V_PKG" ] || [ -z "$V_PLUGIN" ]; then
|
|
34
|
+
echo "✗ No se pudo leer la versión de uno de los archivos JSON. ¿Node disponible?" >&2
|
|
35
|
+
exit 2
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
echo "▶ check-version-sync:"
|
|
39
|
+
printf " VERSION: %s\n" "$V_FILE"
|
|
40
|
+
printf " package.json#version: %s\n" "$V_PKG"
|
|
41
|
+
printf " .claude-plugin/plugin.json#version: %s\n" "$V_PLUGIN"
|
|
42
|
+
|
|
43
|
+
if [ "$V_FILE" = "$V_PKG" ] && [ "$V_PKG" = "$V_PLUGIN" ]; then
|
|
44
|
+
echo "✓ Las 3 versiones están sincronizadas: $V_FILE"
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
echo "" >&2
|
|
49
|
+
echo "✗ Drift detectado. Las 3 fuentes deben coincidir antes de publicar." >&2
|
|
50
|
+
echo " Para arreglar: ajusta los archivos al mismo valor de semver." >&2
|
|
51
|
+
exit 1
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# denylist.txt — términos que NUNCA deben aparecer en el contenido distribuido del arnés
|
|
2
|
+
# (agents/skills/hooks/config/templates/…). docs/examples/ está EXCLUIDO del check.
|
|
3
|
+
# Uno por línea; líneas con # se ignoran. El check usa word-boundaries case-insensitive.
|
|
4
|
+
# Regla: SOLO identificadores de cliente y vocabulario de DOMINIO concreto — nunca
|
|
5
|
+
# sustantivos genéricos (p.ej. NO incluir "scoring", "google-genai", "better-sqlite3":
|
|
6
|
+
# darían falsos positivos en ejemplos pedagógicos neutros).
|
|
7
|
+
|
|
8
|
+
# Clientes Trycore
|
|
9
|
+
CISA
|
|
10
|
+
ICBF
|
|
11
|
+
SAE
|
|
12
|
+
Cruz Roja
|
|
13
|
+
Bienestar Familiar
|
|
14
|
+
DIAN
|
|
15
|
+
|
|
16
|
+
# Proyectos identificables
|
|
17
|
+
inmuebles-cisa
|
|
18
|
+
propuesta-cruz-roja
|
|
19
|
+
docfly
|
|
20
|
+
operator-ms-project
|
|
21
|
+
show-room
|
|
22
|
+
showroom
|
|
23
|
+
|
|
24
|
+
# Dominio KYC concreto (debe vivir solo en docs/examples/)
|
|
25
|
+
KYC
|
|
26
|
+
cédula
|
|
27
|
+
cedula
|
|
28
|
+
Gemini
|
|
29
|
+
GEMINI_API_KEY
|
|
30
|
+
validacion-documental
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: building-a-slice
|
|
3
|
+
description: Use when building, continuing, or shipping a product epic (EP-XXX) end to end — drives the fast inner-loop pipeline (DoR → OpenSpec change linked to its epic → TDD → journey-smoke → api/data → reduced DoD → PR+archive → ask for Release Gate) using the build-state.json file to synchronize agents. Heavy reviews (security/design/UX/three-way coherence/architecture/integration) run once per release in the releasing-a-version skill, not per epic. The epic is the build unit; the HUs it covers are its internal scope. Delegates to opsx:* for changes and superpowers:test-driven-development for TDD; never reimplements them.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Construir un slice (épica EP-XXX) — Build
|
|
7
|
+
|
|
8
|
+
Workflow maestro de **construcción**. Extiende la discovery de Trycore (que termina en flows)
|
|
9
|
+
hacia el código. **Orquesta y delega**: el motor de changes es `opsx:*`, el motor de tests es
|
|
10
|
+
`superpowers:test-driven-development`. Esta skill NO los reimplementa: los secuencia y registra
|
|
11
|
+
el avance en el estado.
|
|
12
|
+
|
|
13
|
+
> **Unidad de construcción: la épica (`EP-XXX`).** Un slice = una épica = un OpenSpec change = una
|
|
14
|
+
> rama = un PR. Las HU de la épica (que siguen viviendo en `docs/04-historias/`) son el **alcance
|
|
15
|
+
> interno** del change y se listan en `active_slice.hus[]`. Construir por HU suelta es sobre-ingeniería.
|
|
16
|
+
|
|
17
|
+
## Principio de operación
|
|
18
|
+
- **Una sola fuente de verdad**: `.claude/state/build-state.json` (schema + protocolo en
|
|
19
|
+
`.claude/state/README.md`). Lee antes de actuar; escribe una vez por transición.
|
|
20
|
+
- **Secuencial**: un slice activo a la vez. Un gate no se salta.
|
|
21
|
+
- **Divulgación progresiva**: carga el `references/<tema>.md` solo cuando la fase lo necesita.
|
|
22
|
+
- **Delega en subagentes** para revisión pesada (devuelven síntesis, protegen el contexto).
|
|
23
|
+
|
|
24
|
+
## Dos loops
|
|
25
|
+
|
|
26
|
+
Esta skill conduce el **inner loop** (rápido, por épica, sin subagentes pesados). Las revisiones
|
|
27
|
+
profundas (seguridad, diseño, UX, coherencia triple, arquitectura, integración) **NO** corren por
|
|
28
|
+
épica: corren **una vez por release** en la skill `releasing-a-version` (outer loop). Objetivo del
|
|
29
|
+
inner loop: **≤ ~20 min por épica** y producto que **camina end-to-end en todo momento**.
|
|
30
|
+
|
|
31
|
+
> **Regla del esqueleto que camina.** El **primer** slice de una release construye el journey
|
|
32
|
+
> completo más delgado posible (de la 1ª a la última actividad del backbone del Story Map), aunque
|
|
33
|
+
> cada paso sea un stub. Cada épica posterior **engorda** un paso de ese esqueleto y mantiene el
|
|
34
|
+
> `journey_smoke` verde. Nunca se construyen capas horizontales aisladas que "se juntan al final".
|
|
35
|
+
|
|
36
|
+
## Pipeline — inner loop (carga la referencia indicada en cada paso)
|
|
37
|
+
|
|
38
|
+
| Fase | Acción | Delega en | Gate | Referencia |
|
|
39
|
+
|---|---|---|---|---|
|
|
40
|
+
| 1 · dor | Validar Definition of Ready | `dor-dod-gatekeeper` | `dor` | `dor.md` |
|
|
41
|
+
| 2 · change | `opsx:new` + bloque `## Trazabilidad`; validar enlace (barato) | `opsx:new`, `change-epic-coherence` | `coherence_link` | `link-change-epic.md` |
|
|
42
|
+
| 3 · tdd | red → green → refactor | `superpowers:test-driven-development` | `tdd` | — |
|
|
43
|
+
| 4 · smoke | Recorrer el journey-hasta-aquí end-to-end | skill `verify` / `run` (+ MCP chrome-devtools) | `journey_smoke` | `mcp-map.md` |
|
|
44
|
+
| 5 · api/data | contratos + consistencia (si aplican al slice) | `api-contract-tester`, `data-consistency-checker` | `api`,`data` | `newman-tests.md`, `data-consistency.md` |
|
|
45
|
+
| 6 · dod | Definition of Done (por slice, reducido) | `dor-dod-gatekeeper` | `dod` | `dod.md` |
|
|
46
|
+
| 7 · pr | Abrir PR + archivar change en el mismo PR | `opsx:archive`, `opsx:sync` | — | `gitflow.md` |
|
|
47
|
+
| 8 · release? | Preguntar si correr el Release Gate ahora | usuario (default computado) | — | abajo |
|
|
48
|
+
|
|
49
|
+
Los gates `stack`, `security`, `smell`, `ux` y la coherencia triple completa **ya no se cierran
|
|
50
|
+
aquí**: pertenecen al Release Gate. Las **deps** siguen vigiladas en tiempo real por el hook
|
|
51
|
+
`stack-guard.sh`; lint/tsc/gitflow por sus hooks.
|
|
52
|
+
|
|
53
|
+
MCP/LSP por gate: ver `references/mcp-map.md`. Protocolo de estado: `references/state-protocol.md`.
|
|
54
|
+
|
|
55
|
+
## Fase 8 · ¿Release Gate ahora? (default computado, humano decide)
|
|
56
|
+
|
|
57
|
+
Tras archivar la épica, **pregunta al usuario** si correr el Release Gate, con un **default
|
|
58
|
+
calculado** desde las líneas de release del Story Map (`docs/02-user-story-map/`):
|
|
59
|
+
|
|
60
|
+
- Si la épica **cierra una línea de release** (todas las épicas de esa línea ya están en
|
|
61
|
+
`history[]`) → default **"Sí, correr `releasing-a-version` ahora"**.
|
|
62
|
+
- Si no la cierra → default **"Continuar a la siguiente épica"**. Excepción (*nudge*): si hay
|
|
63
|
+
**≥ 2 épicas** archivadas desde el último entry de `releases[]`, recomienda correrlo igual.
|
|
64
|
+
|
|
65
|
+
El usuario siempre puede sobreescribir el default. Si acepta, invoca la skill
|
|
66
|
+
**`releasing-a-version`** sobre la release correspondiente.
|
|
67
|
+
|
|
68
|
+
## Cómo empezar
|
|
69
|
+
1. Pregunta/identifica la **épica** objetivo (`EP-XXX` en `docs/03-backlog/epicas.md`) y reúne las
|
|
70
|
+
**HU que cubre** (las que tienen `epica: EP-XXX` en `docs/04-historias/`) → poblarán `hus[]`.
|
|
71
|
+
2. Lee `build-state.json`. Si hay `active_slice`, retoma su primer gate abierto; si es `null`,
|
|
72
|
+
arranca en **dor**.
|
|
73
|
+
3. Invoca al `build-orchestrator` para conducir el pipeline, o ejecuta fase a fase tú mismo
|
|
74
|
+
respetando los gates.
|
|
75
|
+
|
|
76
|
+
## Reglas duras
|
|
77
|
+
- Si `harness_phase` = `authoring` (sin `package.json`), puedes hacer dor + change, pero
|
|
78
|
+
los gates de código (tdd, journey_smoke, api, data) NO se cierran hasta scaffoldear.
|
|
79
|
+
- El enlace change↔épica va en `## Trazabilidad` del `proposal.md`, **nunca** en frontmatter YAML
|
|
80
|
+
(rompe `openspec validate`). Ver `link-change-epic.md`.
|
|
81
|
+
- Integración solo por **PR** a `main` (el hook `gitflow-guard.sh` bloquea commits/push directos).
|
|
82
|
+
- Si una regla aquí contradice la metodología Trycore (`METODOLOGIA.md`), **gana la metodología**.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Consistencia de datos — frontera externa + capa de decisión
|
|
2
|
+
|
|
3
|
+
Guía que aplica `data-consistency-checker`. Dos dominios de datos: el **JSON de esquema fijo** que
|
|
4
|
+
devuelve el servicio externo/IA de la frontera (la "capa de servicios externos") y el **cálculo
|
|
5
|
+
determinista de la capa de decisión del dominio**.
|
|
6
|
+
|
|
7
|
+
Los nombres concretos de campos, las decisiones de alto impacto, los umbrales y los casos borde se
|
|
8
|
+
leen del bloque de dominio del CLAUDE.md del consumidor / del PRD del consumidor (ruta declarada en
|
|
9
|
+
`stack-allowlist.json#source`). Esta guía describe los **patrones de invariante**, no valores de un
|
|
10
|
+
dominio específico. (Para una instanciación concreta de referencia, ver
|
|
11
|
+
`docs/examples/reference/data-consistency.example.md`.)
|
|
12
|
+
|
|
13
|
+
## Esquema de la frontera (servicio externo/IA → JSON de esquema fijo)
|
|
14
|
+
- **Validación dura contra esquema** (p. ej. zod) a la salida del servicio: trata toda salida externa/IA como **entrada no confiable**. Malformado = rechazo controlado, no propagación a la capa de decisión.
|
|
15
|
+
- **Tipos/unidades** consistentes (montos numéricos, fechas ISO 8601, identificadores normalizados), según las reglas del dominio del consumidor.
|
|
16
|
+
- **Campos ausentes** explícitos (`null`/opcional) — nunca valores fantasma o defaults silenciosos.
|
|
17
|
+
- **Idempotencia**: re-procesar la misma entrada produce el mismo JSON (salvo cambios de prompt/contrato versionados).
|
|
18
|
+
|
|
19
|
+
## Capa de decisión del dominio (determinista, sin IA)
|
|
20
|
+
- **Determinismo**: misma entrada → mismo resultado y misma clasificación, ejecutado N veces. Sin `Math.random`, sin reloj, sin IA en el cálculo.
|
|
21
|
+
- **Rango y constantes versionadas**: el resultado está acotado y la clasificación pertenece al conjunto de **las decisiones de alto impacto del dominio** (ejemplo concreto en el domain-pack del consumidor), según **umbrales versionados** (config, no literales dispersos en el código).
|
|
22
|
+
- **Explicabilidad**: Σ(drivers por factor) reconstruye exactamente el total (cuadra al céntimo/punto); el resultado es trazable a sus contribuyentes.
|
|
23
|
+
- **Consistencia cruzada**: las comparaciones entre fuentes/registros (campos de identidad u otros declarados por el consumidor) son consistentes y las discrepancias se atribuyen a la fuente correcta.
|
|
24
|
+
|
|
25
|
+
## Tipos de prueba a exigir
|
|
26
|
+
1. **Schema tests**: fixtures válidos pasan; inválidos (campo faltante, tipo erróneo, valor negativo donde no aplica) fallan con error claro.
|
|
27
|
+
2. **Determinismo**: ejecutar la capa de decisión K veces sobre el mismo input → resultado idéntico.
|
|
28
|
+
3. **Property-based** (recomendado): para inputs generados, el resultado permanece en rango y la suma de drivers cuadra.
|
|
29
|
+
4. **Casos límite**: entradas vacías, valores negativos donde no deberían existir, variantes de texto con acentos/typos, valores en cero, entradas ilegibles. Los casos concretos se derivan del PRD/CLAUDE.md del consumidor.
|
|
30
|
+
5. **No-persistencia de datos regulados/PII**: verificar que el cálculo no escribe datos sensibles / PII regulados crudos (los que el consumidor declara en el bloque de dominio de su CLAUDE.md o su PRD) a la capa de persistencia/`localStorage`/logs.
|
|
31
|
+
|
|
32
|
+
## Veredicto → gate
|
|
33
|
+
Todas las invariantes ✓ con evidencia (test/`archivo:línea`) → `gates.data: true`. Alguna ✗ →
|
|
34
|
+
`false` + el test o fix faltante.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Definition of Done (DoD) — checklist de salida **por slice** (inner loop)
|
|
2
|
+
|
|
3
|
+
Un slice (épica) **no se archiva ni se mergea** hasta cumplir TODO esto. Lo valida
|
|
4
|
+
`dor-dod-gatekeeper` leyendo los gates de `build-state.json`. Es el DoD **reducido**: las revisiones
|
|
5
|
+
pesadas (seguridad, diseño, UX, coherencia triple, arquitectura, integración) **no** se piden aquí
|
|
6
|
+
— se piden una vez por release en el **Release Gate** (`release-dod.md` de la skill
|
|
7
|
+
`releasing-a-version`).
|
|
8
|
+
|
|
9
|
+
- [ ] **`tdd`** — cada escenario AC (G/W/T) de **cada HU de la épica** tiene test; ciclo red→green→refactor completo; suite verde.
|
|
10
|
+
- [ ] **`journey_smoke`** — la app arranca y el **journey-hasta-aquí** (backbone del Story Map cubierto hasta esta épica) **se recorre end-to-end** sin romperse. Se verifica con la skill `verify`/`run` (+ MCP `chrome-devtools` si la app corre). El esqueleto que camina sigue caminando.
|
|
11
|
+
- [ ] **`coherence_link`** — `change-epic-coherence` confirma el enlace change↔épica (bloque `## Trazabilidad`, `openspec validate` ok). Es el chequeo **barato**; la trazabilidad triple completa va al Release Gate.
|
|
12
|
+
- [ ] **`data`** — `data-consistency-checker` valida invariantes de datos (salida de servicios externos validada contra esquema antes de alimentar la capa de decisión determinista del dominio) (si el slice toca datos).
|
|
13
|
+
- [ ] **`api`** — `api-contract-tester` (Newman) 100% verde (o `null` si el slice no tiene endpoints).
|
|
14
|
+
- [ ] **OpenSpec**: todas las tasks `[x]`; el archive del change va **en el mismo PR** (no PR aparte).
|
|
15
|
+
- [ ] **Docs/trazabilidad**: back-ref del change añadida en la épica y en cada HU de `hus[]`.
|
|
16
|
+
- [ ] **Hooks verdes (automáticos, no son gates de agente)**: `lint-typecheck.sh` (lint + chequeo de tipos del stack declarado), `stack-guard.sh` (deps en allowlist según la sección de requisitos técnicos del PRD del consumidor, ruta declarada en `stack-allowlist.json#source`), `gitflow-guard.sh` (rama `feature/*`, sin commits directos a `main`).
|
|
17
|
+
|
|
18
|
+
**Todo ✓** → `gates.dod: true`; se hace `opsx:archive` + se abre/mergea el PR. **Algo ✗** → listar
|
|
19
|
+
gates abiertos y devolver al `build-orchestrator`.
|
|
20
|
+
|
|
21
|
+
> **Lo que NO se valida aquí (va al Release Gate, `releasing-a-version`):** `security`, `smell`
|
|
22
|
+
> (diseño), `ux` (Krug), `coherence` (trazabilidad triple completa) y `stack_arch` (arquitectura
|
|
23
|
+
> según el contrato de stack del PRD del consumidor: servicios externos/IA en la frontera declarada
|
|
24
|
+
> server-side, capa de decisión determinista del dominio sin IA). Las **deps** sí se vigilan por
|
|
25
|
+
> slice, pero vía el hook `stack-guard.sh`, no vía subagente.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Definition of Ready (DoR) — checklist de entrada
|
|
2
|
+
|
|
3
|
+
Una **épica** (`EP-XXX`) **no entra a construcción** hasta cumplir TODO esto. La unidad del slice es
|
|
4
|
+
la épica; lo de abajo aplica a la épica y a **cada HU** que cubre (`hus[]`). Lo valida `dor-dod-gatekeeper`.
|
|
5
|
+
|
|
6
|
+
- [ ] **Épica válida**: `EP-XXX` existe en `docs/03-backlog/epicas.md` con trazabilidad a objetivos del PRD.
|
|
7
|
+
- [ ] **HU enumeradas**: la épica tiene ≥1 HU; todas las que entran se listan en `hus[]`.
|
|
8
|
+
- [ ] **Frontmatter completo** en cada `docs/04-historias/HU-XXX.md`: `id, titulo, epica, prioridad, complejidad, estado` y `estado: lista`.
|
|
9
|
+
- [ ] **AC en Given/When/Then** por HU: 3–5 escenarios, con **happy + error + edge** (regla dura Trycore).
|
|
10
|
+
- [ ] **INVEST** por HU: pasa los 6 criterios (Independent, Negotiable, Valuable, Estimable, Small, Testable). Ante duda, invocar `invest-validator`.
|
|
11
|
+
- [ ] **Dependencias resueltas**: las épicas/HU de las que depende están archivadas (`history[]`) o explícitamente no bloquean.
|
|
12
|
+
- [ ] **Cabe en el stack** del PRD §7 (no requiere tecnología fuera de `stack-allowlist.json`).
|
|
13
|
+
- [ ] **Datos de prueba disponibles** o identificables (p.ej. los datos de ejemplo / fixtures sintéticos del dominio del consumidor).
|
|
14
|
+
|
|
15
|
+
**Si todo ✓** → `dor-dod-gatekeeper` abre `active_slice` en `build-state.json` con `epica`, `hus[]`,
|
|
16
|
+
`phase: dor`, `gates.dor: true` y el resto en `false` (`ux`/`api` en `null` si la épica no toca UI/endpoints).
|
|
17
|
+
**Si algo ✗** → no se abre el slice; se reporta qué falta y se vuelve a discovery (Trycore).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# GitHub Flow (estricto) — Build
|
|
2
|
+
|
|
3
|
+
Modelo de ramas **GitHub Flow**: `main` siempre desplegable; todo cambio nace en una rama corta y
|
|
4
|
+
se integra **solo por Pull Request** con checks verdes. El hook `gitflow-guard.sh` lo hace cumplir
|
|
5
|
+
de forma determinista (bloquea commit/push directo a `main` y ramas no tipadas).
|
|
6
|
+
|
|
7
|
+
## Ciclo por slice
|
|
8
|
+
```bash
|
|
9
|
+
git switch main && git pull --ff-only # parte de main al día
|
|
10
|
+
git switch -c feature/<slug> # rama tipada: feature/* | fix/* | chore/*
|
|
11
|
+
# ... TDD + gates (estado en build-state.json) ...
|
|
12
|
+
git add -A && git commit -m "<tipo>: <mensaje>" # commit en la rama feature (nunca en main)
|
|
13
|
+
git push -u origin feature/<slug> # push de la rama feature (nunca a main)
|
|
14
|
+
gh pr create --base main --head feature/<slug> --fill # integración por PR
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Convenciones
|
|
18
|
+
- **Rama**: `feature/<slug-kebab>` (nuevo valor), `fix/<slug>` (corrección), `chore/<slug>` (infra/docs).
|
|
19
|
+
Una rama por **épica** (= un slice): `feature/ep-003-pricing-engine`.
|
|
20
|
+
- **Commits**: Conventional Commits (`feat:`, `fix:`, `test:`, `refactor:`, `chore:`, `docs:`).
|
|
21
|
+
- **PR**: título claro, descripción enlazando la épica, sus HU (`hus[]`) y el OpenSpec change; checks
|
|
22
|
+
(lint, types, tests, newman) en verde antes de merge; squash recomendado.
|
|
23
|
+
|
|
24
|
+
## Qué bloquea `gitflow-guard.sh`
|
|
25
|
+
- `git commit` estando en `main`/`master`. → crea una rama feature.
|
|
26
|
+
- `git commit` desde una rama que no es `feature/*|fix/*|chore/*`.
|
|
27
|
+
- `git push` apuntando a `main`/`master`. → abre un PR.
|
|
28
|
+
|
|
29
|
+
> No es GitFlow clásico: **no hay `develop` ni `release/*`**. Una sola línea estable (`main`) +
|
|
30
|
+
> ramas cortas + PR.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Usabilidad según Steve Krug ("Don't Make Me Think")
|
|
2
|
+
|
|
3
|
+
Heurísticas que aplica `ux-krug-reviewer` a slices con UI. Objetivo: que el usuario operador del producto opere
|
|
4
|
+
sin fricción cognitiva.
|
|
5
|
+
|
|
6
|
+
## Las leyes de Krug
|
|
7
|
+
1. **Primera ley — "No me hagas pensar".** Todo lo autoevidente; si no, autoexplicativo. Cero acertijos.
|
|
8
|
+
2. **No usamos la web, la escaneamos.** Diseña para el vistazo: jerarquía visual, encabezados,
|
|
9
|
+
fragmentos cortos, lo importante arriba/grande.
|
|
10
|
+
3. **Elegimos la primera opción razonable (satisficing).** No obligues a comparar; ofrece caminos obvios.
|
|
11
|
+
4. **"Omite las palabras innecesarias".** Recorta el ruido textual a la mitad; luego otra vez.
|
|
12
|
+
5. **Convención sobre creatividad.** Botones que parecen botones, enlaces que parecen enlaces,
|
|
13
|
+
navegación donde se espera.
|
|
14
|
+
6. **Haz obvio lo clicable** y da feedback inmediato (hover, loading, disabled, foco).
|
|
15
|
+
|
|
16
|
+
## Aplicado a decisiones de alto impacto
|
|
17
|
+
- La **decisión de alto impacto del dominio** (ejemplo concreto en el domain-pack del consumidor) y su **resultado con su banda/clasificación** deben leerse de un vistazo.
|
|
18
|
+
- Los **drivers o factores que justifican el resultado**: visibles y comprensibles sin abrir documentación.
|
|
19
|
+
- Las **inconsistencias o discrepancias detectadas**: resaltadas y atribuidas a su origen correcto, sin ambigüedad.
|
|
20
|
+
- Estados explícitos: **cargando, vacío, error, sin permisos**; nunca una pantalla muda.
|
|
21
|
+
- Recuperación de error con mensaje accionable (qué pasó y qué hacer), sin filtrar datos sensibles / PII regulados ni stack traces.
|
|
22
|
+
|
|
23
|
+
## Medir, no opinar (cuando la app corre)
|
|
24
|
+
Usa el MCP **chrome-devtools**:
|
|
25
|
+
- `take_snapshot` → inspecciona el árbol de accesibilidad (roles, labels, foco).
|
|
26
|
+
- `lighthouse_audit` → puntuaciones de Accessibility / Best Practices; adjunta fallos concretos.
|
|
27
|
+
Reporta hallazgos como BLOQUEANTE / RECOMENDADO / NIT con la pantalla y el fix.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Enlace OpenSpec change ↔ épica + HU cubiertas (bloque de Trazabilidad)
|
|
2
|
+
|
|
3
|
+
Cada OpenSpec change corresponde a **una épica** (la unidad de construcción) y declara las
|
|
4
|
+
**historia(s)** que cubre. Este enlace es el puente entre la discovery de Trycore (`docs/`) y la
|
|
5
|
+
construcción (`openspec/`). Lo valida `change-epic-coherence`.
|
|
6
|
+
|
|
7
|
+
## Dónde y cómo
|
|
8
|
+
En el **cuerpo markdown** del `openspec/changes/<name>/proposal.md`, añade una sección al final:
|
|
9
|
+
|
|
10
|
+
```markdown
|
|
11
|
+
## Trazabilidad
|
|
12
|
+
- Épica: EP-003
|
|
13
|
+
- Historias: HU-010, HU-011, HU-012
|
|
14
|
+
- Discovery: docs/03-backlog/epicas.md#ep-003
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
> ⚠️ **NO** lo pongas en frontmatter YAML del proposal: OpenSpec valida la estructura del change
|
|
18
|
+
> con `openspec validate --strict` y un frontmatter ajeno puede romperla. El bloque markdown es seguro.
|
|
19
|
+
|
|
20
|
+
## Reglas
|
|
21
|
+
1. **Exactamente una épica** por change = la unidad del slice (un change no cruza épicas). Si
|
|
22
|
+
necesitas dos épicas, son dos slices/changes distintos.
|
|
23
|
+
2. **Las HU de esa épica** que entran en el alcance (las de `hus[]`). Cada `HU-XXX` debe existir y
|
|
24
|
+
su `epica:` debe coincidir con la EP. La lista de `Historias:` debe igualar a `hus[]`.
|
|
25
|
+
3. **Nombre del change**: kebab-case basado en la épica, p.ej. `ep-003-pricing-engine`.
|
|
26
|
+
4. **Back-reference**: al archivar, añade la nota `> OpenSpec change: ep-003-pricing-engine` en la
|
|
27
|
+
épica (`docs/03-backlog/epicas.md`) y en cada HU de `hus[]` (cierra el enlace bidireccional
|
|
28
|
+
Trycore↔OpenSpec).
|
|
29
|
+
|
|
30
|
+
## Validación
|
|
31
|
+
```bash
|
|
32
|
+
openspec validate "<name>" --type change --strict --json
|
|
33
|
+
```
|
|
34
|
+
El agente `change-epic-coherence` corre esto + comprueba existencia de EP/HU + coherencia de alcance.
|