specleap-framework 2.1.0 → 2.1.5

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.
Files changed (75) hide show
  1. package/.agents/backend.md +3 -3
  2. package/.agents/frontend.md +2 -2
  3. package/.agents/producto.md +9 -11
  4. package/.claude/hooks/spec-guard.sh +132 -0
  5. package/.claude/settings.json.template +15 -0
  6. package/.clinerules +3 -3
  7. package/.coderabbit.yaml +2 -4
  8. package/.commands/compliance.md +89 -0
  9. package/.commands/inicio.md +15 -15
  10. package/.commands/nuevo/README.md +2 -2
  11. package/.commands/planificar.md +1 -1
  12. package/.continue/rules/04-git-workflow.md +5 -5
  13. package/.continuerules +3 -4
  14. package/.cursorrules +1 -1
  15. package/.github/copilot-instructions.md +1 -1
  16. package/.specleap/i18n/en.json +177 -0
  17. package/.specleap/i18n/es.json +177 -0
  18. package/.specleap/i18n.sh +63 -0
  19. package/CHANGELOG.md +276 -0
  20. package/CLAUDE.md +54 -13
  21. package/README.md +169 -528
  22. package/SETUP.md +16 -13
  23. package/openspec/INDEX.md +53 -0
  24. package/openspec/README.md +104 -0
  25. package/openspec/SPEC-FORMAT.md +168 -0
  26. package/openspec/changes/.gitkeep +0 -0
  27. package/openspec/cli/COMMAND_REFERENCE.md +817 -0
  28. package/openspec/cli/README.md +189 -0
  29. package/openspec/cli/apply.sh +229 -0
  30. package/openspec/cli/archive.sh +240 -0
  31. package/openspec/cli/code-review.sh +207 -0
  32. package/openspec/cli/common.sh +171 -0
  33. package/openspec/cli/enrich.sh +188 -0
  34. package/openspec/cli/ff.sh +329 -0
  35. package/openspec/cli/new.sh +260 -0
  36. package/openspec/cli/openspec +82 -0
  37. package/openspec/cli/report.sh +244 -0
  38. package/openspec/cli/status.sh +178 -0
  39. package/openspec/cli/verify.sh +246 -0
  40. package/openspec/config.yaml +76 -0
  41. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/00-original-user-story.md +5 -0
  42. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/01-refined-user-story.md +106 -0
  43. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/README.md +333 -0
  44. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/design.md +461 -0
  45. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/proposal.md +124 -0
  46. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/specs/functional/F001-authentication.spec.md +399 -0
  47. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/specs/technical/T001-jwt-implementation.spec.md +606 -0
  48. package/openspec/examples/CHANGE-SAMPLE-001-user-authentication/tasks.md +433 -0
  49. package/openspec/examples/MERMAID_DIAGRAMS.md +481 -0
  50. package/openspec/examples/README.md +334 -0
  51. package/openspec/specs/functional/.gitkeep +0 -0
  52. package/openspec/specs/integration/.gitkeep +0 -0
  53. package/openspec/specs/security/.gitkeep +0 -0
  54. package/openspec/specs/technical/.gitkeep +0 -0
  55. package/openspec/templates/.coderabbit.yaml +259 -0
  56. package/openspec/templates/design.md +181 -0
  57. package/openspec/templates/proposal.md +79 -0
  58. package/openspec/templates/tasks.md +193 -0
  59. package/package.json +10 -5
  60. package/rules/git-workflow.md +3 -3
  61. package/rules/session-protocol.md +3 -3
  62. package/scripts/README.md +13 -25
  63. package/scripts/compliance-audit.sh +325 -0
  64. package/scripts/generate-contract.sh +4 -4
  65. package/scripts/install-skills.sh +12 -11
  66. package/scripts/lib/render-contrato.py +1 -1
  67. package/scripts/quality-baseline.sh +210 -0
  68. package/scripts/quality-healing.sh +241 -0
  69. package/setup.sh +3 -3
  70. package/.claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
  71. package/.claude/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
  72. package/.claude/skills/ui-ux-pro-max/scripts/__pycache__/search.cpython-314.pyc +0 -0
  73. package/scripts/lib/jira-project-utils.sh +0 -222
  74. package/scripts/setup-mcp.sh +0 -654
  75. package/scripts/test-cuestionario.sh +0 -428
@@ -0,0 +1,241 @@
1
+ #!/bin/bash
2
+ # SpecLeap — Healing telemetry log per feature
3
+ # Writes JSONL entries to .quality/evidence/[feature]/healing.jsonl
4
+ #
5
+ # Verbs:
6
+ # log append a new entry
7
+ # show print last N entries (default 20)
8
+ # stats count entries by severity, phase and action
9
+
10
+ set -e
11
+
12
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
+ ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
14
+
15
+ source "$ROOT/.specleap/i18n.sh"
16
+
17
+ EVIDENCE_DIR="$ROOT/.quality/evidence"
18
+
19
+ GREEN='\033[0;32m'
20
+ YELLOW='\033[1;33m'
21
+ RED='\033[0;31m'
22
+ NC='\033[0m'
23
+
24
+ # -----------------------------------------------------------------------------
25
+ # Argument parser (long options only)
26
+ # Sets: ARG_FEATURE, ARG_PHASE, ARG_SEVERITY, ARG_ACTION, ARG_DETAIL, ARG_FILE, ARG_LAST
27
+ # -----------------------------------------------------------------------------
28
+ parse_args() {
29
+ ARG_FEATURE=""
30
+ ARG_PHASE=""
31
+ ARG_SEVERITY=""
32
+ ARG_ACTION=""
33
+ ARG_DETAIL=""
34
+ ARG_FILE=""
35
+ ARG_LAST="20"
36
+
37
+ while [[ $# -gt 0 ]]; do
38
+ case "$1" in
39
+ --feature) ARG_FEATURE="$2"; shift 2 ;;
40
+ --phase) ARG_PHASE="$2"; shift 2 ;;
41
+ --severity) ARG_SEVERITY="$2"; shift 2 ;;
42
+ --action) ARG_ACTION="$2"; shift 2 ;;
43
+ --detail) ARG_DETAIL="$2"; shift 2 ;;
44
+ --file) ARG_FILE="$2"; shift 2 ;;
45
+ --last) ARG_LAST="$2"; shift 2 ;;
46
+ *) shift ;;
47
+ esac
48
+ done
49
+ }
50
+
51
+ # -----------------------------------------------------------------------------
52
+ # Resolve path to the healing.jsonl of a given feature
53
+ # Outputs path via stdout; returns non-zero if evidence folder missing
54
+ # -----------------------------------------------------------------------------
55
+ log_path_for() {
56
+ local feature="$1"
57
+ local dir="$EVIDENCE_DIR/$feature"
58
+ if [ ! -d "$dir" ]; then
59
+ return 1
60
+ fi
61
+ echo "$dir/healing.jsonl"
62
+ }
63
+
64
+ # -----------------------------------------------------------------------------
65
+ # JSON-escape a string (wraps jq)
66
+ # -----------------------------------------------------------------------------
67
+ json_escape() {
68
+ if command -v jq &> /dev/null; then
69
+ jq -Rn --arg s "$1" '$s'
70
+ else
71
+ # Fallback: crude escaping for common cases
72
+ local s="$1"
73
+ s="${s//\\/\\\\}"
74
+ s="${s//\"/\\\"}"
75
+ s="${s//$'\n'/\\n}"
76
+ s="${s//$'\t'/\\t}"
77
+ echo "\"$s\""
78
+ fi
79
+ }
80
+
81
+ cmd_log() {
82
+ parse_args "$@"
83
+
84
+ if [ -z "$ARG_FEATURE" ]; then
85
+ echo -e "${RED}$(t 'quality.healing.missing_feature')${NC}"
86
+ echo "$(t 'quality.healing.usage_log')"
87
+ exit 1
88
+ fi
89
+ if [ -z "$ARG_PHASE" ]; then
90
+ echo -e "${RED}$(t 'quality.healing.missing_phase')${NC}"
91
+ exit 1
92
+ fi
93
+ if [ -z "$ARG_ACTION" ]; then
94
+ echo -e "${RED}$(t 'quality.healing.missing_action')${NC}"
95
+ exit 1
96
+ fi
97
+
98
+ # Default severity = info
99
+ [ -z "$ARG_SEVERITY" ] && ARG_SEVERITY="info"
100
+
101
+ case "$ARG_SEVERITY" in
102
+ info|warn|error) ;;
103
+ *)
104
+ echo -e "${RED}$(t 'quality.healing.severity_invalid')${NC} $ARG_SEVERITY"
105
+ exit 1
106
+ ;;
107
+ esac
108
+
109
+ local log_file
110
+ if ! log_file=$(log_path_for "$ARG_FEATURE"); then
111
+ echo -e "${RED}$(t 'quality.healing.no_evidence')${NC} $ARG_FEATURE"
112
+ echo "$(t 'quality.healing.run_new_evidence_first')"
113
+ exit 1
114
+ fi
115
+
116
+ local ts
117
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
118
+
119
+ # Build JSON entry one line
120
+ local entry
121
+ if command -v jq &> /dev/null; then
122
+ entry=$(jq -cn \
123
+ --arg ts "$ts" \
124
+ --arg phase "$ARG_PHASE" \
125
+ --arg severity "$ARG_SEVERITY" \
126
+ --arg action "$ARG_ACTION" \
127
+ --arg detail "$ARG_DETAIL" \
128
+ --arg file "$ARG_FILE" \
129
+ '{ts: $ts, phase: $phase, severity: $severity, action: $action, detail: $detail, file: $file}
130
+ | if .file == "" then del(.file) else . end
131
+ | if .detail == "" then del(.detail) else . end')
132
+ else
133
+ # Fallback without jq
134
+ local json="{\"ts\":$(json_escape "$ts"),\"phase\":$(json_escape "$ARG_PHASE"),\"severity\":$(json_escape "$ARG_SEVERITY"),\"action\":$(json_escape "$ARG_ACTION")"
135
+ [ -n "$ARG_DETAIL" ] && json="$json,\"detail\":$(json_escape "$ARG_DETAIL")"
136
+ [ -n "$ARG_FILE" ] && json="$json,\"file\":$(json_escape "$ARG_FILE")"
137
+ json="$json}"
138
+ entry="$json"
139
+ fi
140
+
141
+ echo "$entry" >> "$log_file"
142
+
143
+ echo -e "${GREEN}$(t 'quality.healing.log_done')${NC} $log_file"
144
+ }
145
+
146
+ cmd_show() {
147
+ parse_args "$@"
148
+
149
+ if [ -z "$ARG_FEATURE" ]; then
150
+ echo -e "${RED}$(t 'quality.healing.missing_feature')${NC}"
151
+ echo "$(t 'quality.healing.usage_show')"
152
+ exit 1
153
+ fi
154
+
155
+ local log_file
156
+ if ! log_file=$(log_path_for "$ARG_FEATURE"); then
157
+ echo -e "${RED}$(t 'quality.healing.no_evidence')${NC} $ARG_FEATURE"
158
+ exit 1
159
+ fi
160
+
161
+ if [ ! -f "$log_file" ]; then
162
+ echo -e "${YELLOW}$(t 'quality.healing.no_log')${NC} $ARG_FEATURE"
163
+ exit 0
164
+ fi
165
+
166
+ local total
167
+ total=$(wc -l < "$log_file" | tr -d ' ')
168
+
169
+ echo "healing.jsonl — $ARG_FEATURE — $total $(t 'quality.healing.entries')"
170
+ echo ""
171
+
172
+ if command -v jq &> /dev/null; then
173
+ tail -n "$ARG_LAST" "$log_file" | jq -r '"[\(.ts)] \(.severity | ascii_upcase) \(.phase) / \(.action)\t\(.detail // "")"'
174
+ else
175
+ tail -n "$ARG_LAST" "$log_file"
176
+ fi
177
+ }
178
+
179
+ cmd_stats() {
180
+ parse_args "$@"
181
+
182
+ if [ -z "$ARG_FEATURE" ]; then
183
+ echo -e "${RED}$(t 'quality.healing.missing_feature')${NC}"
184
+ echo "$(t 'quality.healing.usage_stats')"
185
+ exit 1
186
+ fi
187
+
188
+ local log_file
189
+ if ! log_file=$(log_path_for "$ARG_FEATURE"); then
190
+ echo -e "${RED}$(t 'quality.healing.no_evidence')${NC} $ARG_FEATURE"
191
+ exit 1
192
+ fi
193
+
194
+ if [ ! -f "$log_file" ]; then
195
+ echo -e "${YELLOW}$(t 'quality.healing.no_log')${NC} $ARG_FEATURE"
196
+ exit 0
197
+ fi
198
+
199
+ if ! command -v jq &> /dev/null; then
200
+ echo -e "${RED}$(t 'quality.healing.jq_required')${NC}"
201
+ exit 1
202
+ fi
203
+
204
+ local total
205
+ total=$(wc -l < "$log_file" | tr -d ' ')
206
+
207
+ echo "healing.jsonl — $ARG_FEATURE"
208
+ echo "$(t 'quality.healing.total_entries'): $total"
209
+ echo ""
210
+
211
+ echo "$(t 'quality.healing.by_severity'):"
212
+ jq -r '.severity' "$log_file" | sort | uniq -c | sort -rn | awk '{printf " %-8s %s\n", $2, $1}'
213
+ echo ""
214
+
215
+ echo "$(t 'quality.healing.by_phase'):"
216
+ jq -r '.phase' "$log_file" | sort | uniq -c | sort -rn | awk '{printf " %-20s %s\n", $2, $1}'
217
+ echo ""
218
+
219
+ echo "$(t 'quality.healing.by_action'):"
220
+ jq -r '.action' "$log_file" | sort | uniq -c | sort -rn | awk '{printf " %-25s %s\n", $2, $1}'
221
+ }
222
+
223
+ # Dispatch
224
+ case "${1:-}" in
225
+ log)
226
+ shift
227
+ cmd_log "$@"
228
+ ;;
229
+ show)
230
+ shift
231
+ cmd_show "$@"
232
+ ;;
233
+ stats)
234
+ shift
235
+ cmd_stats "$@"
236
+ ;;
237
+ *)
238
+ echo "$(t 'quality.healing.usage')"
239
+ exit 1
240
+ ;;
241
+ esac
package/setup.sh CHANGED
@@ -72,7 +72,7 @@ if [ "$LANG" = "es" ]; then
72
72
  MSG_REQUIREMENTS="Verificando requisitos del sistema..."
73
73
  MSG_GITHUB="Paso 2/6: Configuración GitHub"
74
74
  MSG_ASANA="Paso 3/6: Configuración Asana (Obligatorio)"
75
- MSG_SKILLS="Paso 4/6: Agent Skills (20 skills)"
75
+ MSG_SKILLS="Paso 4/6: Agent Skills (34 skills)"
76
76
  MSG_CODERABBIT="Paso 5/6: CodeRabbit"
77
77
  MSG_FINAL="Paso 6/6: Finalizando"
78
78
  MSG_SUCCESS="✅ ¡Instalación completa!"
@@ -84,7 +84,7 @@ else
84
84
  MSG_REQUIREMENTS="Checking system requirements..."
85
85
  MSG_GITHUB="Step 2/6: GitHub Setup"
86
86
  MSG_ASANA="Step 3/6: Asana Setup (Required)"
87
- MSG_SKILLS="Step 4/6: Agent Skills (20 skills)"
87
+ MSG_SKILLS="Step 4/6: Agent Skills (34 skills)"
88
88
  MSG_CODERABBIT="Step 5/6: CodeRabbit"
89
89
  MSG_FINAL="Step 6/6: Finishing"
90
90
  MSG_SUCCESS="✅ Installation complete!"
@@ -290,7 +290,7 @@ echo ""
290
290
  sleep 1
291
291
 
292
292
  # ============================================
293
- # PASO 4: Agent Skills (20 TIER 1)
293
+ # PASO 4: Agent Skills (34 skills: 20 TIER 1 + 14 TIER 2)
294
294
  # ============================================
295
295
 
296
296
  echo -e "${CYAN}${LINE}${NC}"
@@ -1,222 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # SpecLeap — Utilidades para gestión de proyectos Jira
4
- # Funciones para crear/verificar proyectos Jira independientes
5
-
6
- set -euo pipefail
7
-
8
- # Colores
9
- RED='\033[0;31m'
10
- GREEN='\033[0;32m'
11
- YELLOW='\033[1;33m'
12
- CYAN='\033[0;36m'
13
- RESET='\033[0m'
14
-
15
- print_success() {
16
- echo -e "${GREEN}✅ $1${RESET}" >&2
17
- }
18
-
19
- print_error() {
20
- echo -e "${RED}❌ Error: $1${RESET}" >&2
21
- }
22
-
23
- print_warning() {
24
- echo -e "${YELLOW}⚠️ $1${RESET}" >&2
25
- }
26
-
27
- print_info() {
28
- echo -e "${CYAN}ℹ️ $1${RESET}" >&2
29
- }
30
-
31
- # ============================================================================
32
- # GENERACIÓN DE PROJECT KEY
33
- # ============================================================================
34
-
35
- generate_project_key() {
36
- local project_name="$1"
37
-
38
- # Convertir nombre a key válida de Jira:
39
- # - Solo mayúsculas
40
- # - Sin guiones ni espacios (reemplazar con nada)
41
- # - Máximo 10 caracteres
42
- # - Mínimo 2 caracteres
43
-
44
- # Ejemplos:
45
- # "casa-de-peli" → "CASADEPELI" → "CASADEPEL" (10 chars)
46
- # "mi-app" → "MIAPP" (5 chars)
47
- # "e-commerce" → "ECOMMERCE" → "ECOMMERCE" (9 chars)
48
-
49
- local key=$(echo "$project_name" | tr '[:lower:]' '[:upper:]' | tr -d '-_ ' | head -c 10)
50
-
51
- # Validar longitud mínima
52
- if [[ ${#key} -lt 2 ]]; then
53
- print_error "Project key muy corto: $key (mínimo 2 caracteres)"
54
- return 1
55
- fi
56
-
57
- echo "$key"
58
- }
59
-
60
- # ============================================================================
61
- # VERIFICACIÓN DE PROYECTO JIRA
62
- # ============================================================================
63
-
64
- jira_project_exists() {
65
- local project_key="$1"
66
-
67
- # Intentar obtener info del proyecto vía MCP Jira
68
- # Si el proyecto no existe, el comando fallará
69
-
70
- # Método 1: Usar MCP Jira (si está configurado)
71
- if command -v mcp-jira &> /dev/null; then
72
- if mcp-jira get-project "$project_key" &> /dev/null; then
73
- return 0 # Proyecto existe
74
- else
75
- return 1 # Proyecto no existe
76
- fi
77
- fi
78
-
79
- # Método 2: Usar Jira CLI (si está instalado)
80
- if command -v jira &> /dev/null; then
81
- if jira project view "$project_key" &> /dev/null 2>&1; then
82
- return 0
83
- else
84
- return 1
85
- fi
86
- fi
87
-
88
- # Método 3: Verificación manual (sin herramientas)
89
- print_warning "No se puede verificar proyecto automáticamente (MCP Jira no encontrado)"
90
- print_info "Por favor verifica manualmente si el proyecto $project_key existe en Jira"
91
-
92
- # Preguntar al usuario
93
- read -p "¿El proyecto $project_key existe en Jira? [s/N]: " -n 1 -r >&2
94
- echo >&2
95
-
96
- if [[ $REPLY =~ ^[Ss]$ ]]; then
97
- return 0
98
- else
99
- return 1
100
- fi
101
- }
102
-
103
- # ============================================================================
104
- # CREACIÓN DE PROYECTO JIRA
105
- # ============================================================================
106
-
107
- create_jira_project() {
108
- local project_key="$1"
109
- local project_name="$2"
110
- local project_description="$3"
111
- local lead_email="${4:-}" # Opcional
112
-
113
- print_info "Intentando crear proyecto Jira: $project_key ($project_name)"
114
-
115
- # Método 1: Usar MCP Jira (si está configurado)
116
- if command -v mcp-jira &> /dev/null; then
117
- print_info "Usando MCP Jira para crear proyecto..."
118
-
119
- if mcp-jira create-project \
120
- --key "$project_key" \
121
- --name "$project_name" \
122
- --description "$project_description" \
123
- --type scrum \
124
- ${lead_email:+--lead "$lead_email"} 2>&1; then
125
-
126
- print_success "Proyecto $project_key creado exitosamente"
127
- return 0
128
- else
129
- print_error "Fallo al crear proyecto con MCP Jira"
130
- return 1
131
- fi
132
- fi
133
-
134
- # Método 2: Usar Jira CLI (si está instalado)
135
- if command -v jira &> /dev/null; then
136
- print_info "Usando Jira CLI para crear proyecto..."
137
-
138
- if jira project create \
139
- --key "$project_key" \
140
- --name "$project_name" \
141
- --template "Scrum software development" \
142
- ${lead_email:+--lead "$lead_email"} 2>&1; then
143
-
144
- print_success "Proyecto $project_key creado exitosamente"
145
- return 0
146
- else
147
- print_error "Fallo al crear proyecto con Jira CLI"
148
- return 1
149
- fi
150
- fi
151
-
152
- # Método 3: Instrucciones manuales (sin herramientas)
153
- print_warning "No se puede crear proyecto automáticamente (herramientas no encontradas)"
154
- print_info ""
155
- print_info "Por favor crea el proyecto manualmente en Jira:"
156
- print_info ""
157
- print_info " 1. Ve a Jira → Proyectos → Crear proyecto"
158
- print_info " 2. Selecciona: Scrum software development"
159
- print_info " 3. Clave del proyecto: $project_key"
160
- print_info " 4. Nombre del proyecto: $project_name"
161
- print_info " 5. Descripción: $project_description"
162
- print_info ""
163
-
164
- read -p "¿Ya creaste el proyecto $project_key en Jira? [s/N]: " -n 1 -r >&2
165
- echo >&2
166
-
167
- if [[ $REPLY =~ ^[Ss]$ ]]; then
168
- print_success "Proyecto $project_key confirmado"
169
- return 0
170
- else
171
- print_error "Operación cancelada. Crea el proyecto en Jira y vuelve a ejecutar."
172
- return 1
173
- fi
174
- }
175
-
176
- # ============================================================================
177
- # FLUJO COMPLETO: VERIFICAR O CREAR PROYECTO
178
- # ============================================================================
179
-
180
- ensure_jira_project_exists() {
181
- local project_key="$1"
182
- local project_name="$2"
183
- local project_description="$3"
184
- local lead_email="${4:-}" # Opcional
185
-
186
- print_info "Verificando proyecto Jira: $project_key"
187
-
188
- if jira_project_exists "$project_key"; then
189
- print_success "Proyecto $project_key ya existe"
190
- return 0
191
- else
192
- print_warning "Proyecto $project_key no existe. Creando..."
193
-
194
- if create_jira_project "$project_key" "$project_name" "$project_description" "$lead_email"; then
195
- return 0
196
- else
197
- print_error "No se pudo crear el proyecto $project_key"
198
- return 1
199
- fi
200
- fi
201
- }
202
-
203
- # ============================================================================
204
- # VALIDACIÓN DE KEY
205
- # ============================================================================
206
-
207
- validate_project_key() {
208
- local key="$1"
209
-
210
- # Reglas de Jira para project keys:
211
- # - Solo letras mayúsculas (A-Z)
212
- # - Longitud: 2-10 caracteres
213
- # - Debe empezar con letra
214
-
215
- if [[ ! "$key" =~ ^[A-Z][A-Z0-9]{1,9}$ ]]; then
216
- print_error "Project key inválida: $key"
217
- print_error "Debe contener solo mayúsculas, 2-10 caracteres, empezar con letra"
218
- return 1
219
- fi
220
-
221
- return 0
222
- }