---
name: comfyui_update_skill_score
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: impure
signature: "def comfyui_update_skill_score(slug: str, new_score: float, *, library_dir: str = None) -> dict"
description: "Acumula el score de un juicio en la media de una skill ComfyUI (score_mean/score_n) por media incremental, reescribiendo recipe.json en sitio. A diferencia de comfyui_save_skill NO crea snapshot versions/vN.json ni entrada en growth_log: el score es telemetria de la version vigente, no una version nueva (los snapshots los reserva comfyui_bump_skill_version). library_dir default ~/ComfyUI/skills_library. Slug inexistente o score no numerico -> ok=False. Impura: disco. Nunca lanza."
error_type: error_py_core
tags: [comfyui, comfyui-skill, ml, skill, scoring]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
imports: []
params:
  - name: slug
    desc: "Slug de la skill (su carpeta en la libreria)."
  - name: new_score
    desc: "Score 0-10 del ultimo juicio (p.ej. comfyui_judge_image(...)['score'])."
  - name: library_dir
    desc: "Raiz de la libreria. Default ~/ComfyUI/skills_library. keyword-only."
output: "dict {ok, slug, score_mean, score_n, prev_score_mean, prev_score_n, error}. En exito score_mean/score_n son los valores actualizados. Slug inexistente / score no numerico / fallo de escritura -> ok=False; nunca lanza."
tested: true
tests: [test_golden_media_incremental, test_edge_sin_campos_previos, test_error_skill_inexistente, test_error_score_no_numerico]
test_file_path: "python/functions/ml/tests/test_comfyui_update_skill_score.py"
file_path: "python/functions/ml/comfyui_update_skill_score.py"
---

# comfyui_update_skill_score

Acumulador de telemetría del grupo [`comfyui-skill`](../../../docs/capabilities/comfyui-skill.md).
Cada juicio del panel [`comfyui-judge`](../../../docs/capabilities/comfyui-judge.md) sobre una
imagen de la skill se incorpora a la media `score_mean`/`score_n` de la receta, reescribiendo
`recipe.json` en sitio. Es lo que el pipeline `comfyui_generate_with_skill_oneshot` llama por dentro.

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_update_skill_score import comfyui_update_skill_score

# Tras juzgar una imagen de la skill con score 7.4:
res = comfyui_update_skill_score("portrait_cinematic_sd15", 7.4)
print(res["score_mean"], res["score_n"])   # media acumulada y nº de juicios
```

## Cuando usarla

Después de puntuar una imagen generada por una skill (su receta canónica, sin variantes ad-hoc),
para que `score_mean` refleje la calidad media observada. Normalmente NO se llama directo: lo hace
`comfyui_generate_with_skill_oneshot` cuando `judge=True` y no hay `recipe_patch`. Llámala a mano
solo si juzgas por separado.

## Gotchas

- **In-place, sin snapshot**: reescribe `recipe.json` y nada más. No toca `versions/` ni
  `growth_log` — eso lo reserva `comfyui_bump_skill_version` para versiones reales.
- **Media incremental** `mean_k = mean_{k-1} + (x - mean_{k-1})/k`: estable numéricamente, no
  necesita re-leer el histórico. `score_mean` se redondea a 4 decimales.
- **No acumules variantes**: si juzgas una variante de prueba (un `recipe_patch` no guardado), NO
  la metas en la media de la skill canónica — contaminaría `score_mean`. El pipeline ya lo evita.
