Skip to content

Referencia de métricas y códigos ​

Hoja de referencia densa para todo lo que reporta harness-score: puntajes, scopes, niveles, dimensiones, IDs de check, claves de configuración, flags de CLI, inputs de Action y campos JSON. Las recetas de remediación están en capítulo 8 — Medir y mejorar.

Puntajes: maturity vs effective ​

CódigoQué incluyeSe usa para
maturitySolo archivos del repositorio (scopes: repo)Gate de CI por defecto, badge, --min-level, madurez oficial del equipo
effectiveRepo ∪ scopes globales/extras configuradosLocal: “lo que el agente ve en esta máquina” cuando el harness user/system está habilitado

Sin scopes extra configurados, effective iguala maturity (mismo nivel, puntaje y checks). El reporte siempre incluye ambos bloques para JSON estable.

Define qué puntaje hace gate en CI con gate en config, --gate o el input gate de la Action (maturity por defecto).

Scopes ​

ScopeSignificadoQué se escanea
repoSiempre activoEl directorio que pasas a harness-score (default .). Cuando la raíz del scan es un repositorio plugin Claude Code o Cursor (.claude-plugin/plugin.json o .cursor-plugin/plugin.json en la raíz), skills/, commands/, agents/ y hooks/hooks.json default cuentan como .claude/... / .cursor/....
userOpt-inRutas allowlisted mapeadas a formas repo-relative: ~/.cursor/*, ~/.claude/*, plugins Claude Code user-scoped en ~/.claude/plugins/installed_plugins.json, ~/.codeium/windsurf/* (alias Windsurf), ~/Documents/Cline/Rules → .clinerules/, ~/.continue/{rules,prompts}, ~/.agents/*, ~/.zed/commands, ~/.config/opencode/agents, etc. Ver multi-harness — user scope por herramienta. No incluye: Copilot global (solo repo), reglas inline de Continue en config.yaml, User Rules de Cursor solo en UI, caché de plugins Cursor en usuario (v1).
systemOpt-inReservado para instalaciones validadas a nivel sistema (mínimo en v1)
extraRootsOpt-inDirectorios adicionales (relativos o absolutos) cuyo árbol refleja el layout del harness — ej.: checkout compartido de harness del equipo

Los archivos del proyecto ganan sobre rutas de overlay en conflicto (misma ruta relativa).

No escaneado: Cursor User Rules guardadas solo en la UI del IDE (no en disco), recorridos arbitrarios del home directory, o contenido de secretos en strings de evidencia.

Niveles (L0–L4) ​

Los nombres oficiales de nivel aplican a maturity, salvo que definas gate: effective.

NivelNombreRequisitos (todos los niveles anteriores +)
L0Unharnessed—
L1Documentedcontext ≥ 40%
L2Guidedcontext ≥ 60%; skills ≥ 30% o hooks ≥ 30%; hygiene ≥ 50%
L3Sensingsensors ≥ 60%; ci ≥ 50%
L4Self-correctinghooks ≥ 70%; total ≥ 80%

Narrativa completa: El modelo de madurez.

Dimensiones ​

IDTítuloPts máxMide
contextContext & Guides20AGENTS.md, rules con scope, README
skillsSkills & Commands17Skills, commands/workflows, subagents
hooksHooks & Guardrails14Configuraciones de hooks de Cursor, Claude Code y Devin
sensorsSensors & Feedback20Tests, linter, tipos, formatter
ciCI Feedback14Pipeline, pre-commit
hygieneHygiene & Safety23.gitignore, secretos, lockfile, licencia, higiene MCP

Total: 108 puntos cuando todos los checks aplican. El score.max de un scan es menor cuando un check no aplica (checks[].applicable es false) o está en "off".

Catálogo de checks ​

IDs estables — vinculados a remediación en Medir y mejorar.

Context & Guides ​

IDPtsAnaliza exactamenteRemediación
CTX-014Root AGENTS.md, CLAUDE.md o GEMINI.md, o .claude/CLAUDE.md / .claude/AGENTS.mdctx-01
CTX-023El archivo de contexto tiene ≥20 líneas significativas y ≥2 headingsctx-02
CTX-034Al menos un archivo de rule con scope (cualquier herramienta), .claude/rules/**/*.md, o contexto anidado en subdirectorio de códigoctx-03
CTX-043Toda rule declara metadatos de activación en frontmatterctx-04
CTX-052No toda rule es always-on genéricactx-05
CTX-062Ningún archivo de rule único supera 500 líneasctx-06
CTX-071README.md en la raíz del repositorioctx-07
CTX-081Sin .cursorrules legacy sin rules modernas con scopectx-08

Skills & Commands ​

IDPtsAnaliza exactamenteRemediación
SKL-014Al menos un SKILL.md bajo directorio de skills reconocidoskl-01
SKL-023Toda skill tiene name: y description: en frontmatterskl-02
SKL-033Existen archivos command/workflow para cualquier herramienta soportadaskl-03
SKL-042Las descripciones de skill tienen ≥40 caracteresskl-04
AGT-013Al menos un archivo markdown de subagentagt-01
AGT-022Todo subagent tiene frontmatter name: y description:agt-02

Hooks & Guardrails ​

IDPtsAnaliza exactamenteRemediación
HKS-014Existe una config de hooks de Cursor, Claude Code o Devin y parsea como JSONhks-01
HKS-022Eventos y handlers tipados son estructuralmente válidos; un evento válido desconocido avisahks-02
HKS-034Hook clase gate registrado (shell/MCP/read/tool gate)hks-03
HKS-042Hook clase feedback registrado (post-edit/tool)hks-04
HKS-052Toda ruta local en ejecutables y args existe; handlers sin comando no aplicanhks-05

Sensors & Feedback ​

IDPtsAnaliza exactamenteRemediación
SNS-016Test runner configurado (script en package.json, pytest, phpunit.xml, pest, go test, node --test, …)sns-01
SNS-025Linter configurado (eslint, biome, ruff, phpcs, rector, golangci-lint, …)sns-02
SNS-034Type checking configurado (tsconfig, mypy, pyright, ty, phpstan, psalm, …)sns-03
SNS-043Formatter configurado (prettier, black, pint, php-cs-fixer, gofmt, …)sns-04
SNS-052Al menos un archivo de test existe en el árbolsns-05

CI Feedback ​

IDPtsAnaliza exactamenteRemediación
CI-014Archivo de pipeline CI presente (GitHub Actions, GitLab CI, …)ci-01
CI-024CI ejecuta comandos de pruebas (phpunit, pest, …; resuelve scripts Composer referenciados; ignora las etiquetas de pasos)ci-02
CI-033CI ejecuta comandos de lint o typecheck (phpstan, pint, phpcs, …; resuelve scripts Composer referenciados; ignora las etiquetas de pasos)ci-03
CI-043Herramienta pre-commit o git hook instaladaci-04

Hygiene & Safety ​

IDPtsAnaliza exactamenteRemediación
HYG-012.gitignore presentehyg-01
HYG-023.gitignore cubre archivos de entornohyg-02
HYG-034Sin archivos .env desprotegidos (sin patrón .env.example)hyg-03
HYG-044Configs JSON de MCP sin patrones inline de credencialhyg-04
HYG-052Archivo LICENSE presentehyg-05
HYG-062Sin firmas tipo credencial en markdown/JSON de harnesshyg-06
HYG-073Lockfile de dependencias commiteadohyg-07
HYG-083Configs MCP usan interpolación de env para secretoshyg-08

Archivo de configuración (.harness-score.json) ​

JSON opcional en la raíz del scan (schema estricto — claves desconocidas generan error):

json
{
  "scan": {
    "includePaths": ["build/ci"]
  },
  "scopes": {
    "user": false,
    "system": false
  },
  "extraRoots": [
    { "id": "team-shared", "path": "../shared-harness" }
  ],
  "gate": "maturity",
  "extends": ["no-hooks"],
  "rules": {
    "HYG-05": "off"
  }
}
ClaveTipoDefaultSignificado
scopes.userbooleanfalseIncluir overlay de harness a nivel usuario
scopes.systembooleanfalseIncluir overlay a nivel sistema
extraRoots{ id, path }[][]Árboles extra de harness fusionados en effective
scan.includePathsstring[][]Archivos/directorios exactos, relativos a la raíz, que se incluyen dentro de directorios normalmente omitidos; sin globs
gate"maturity" | "effective""maturity"Qué puntaje usa --min-level
extendsstring[][]Presets con nombre a aplicar (ver abajo)
rulesRecord<checkId, severity>{}Override de severidad por check, aplicado después de cada preset en extends

Precedencia: flags de CLI → inputs de Action → archivo de configuración → valores predeterminados. scan.includePaths, extends y rules se configuran en el archivo; usa --config <path> para indicar un .harness-score.json que los defina. GitHub Action lee el mismo archivo.

scan.includePaths acepta rutas exactas relativas a la raíz del repositorio, con separadores /. Una ruta puede señalar un archivo o directorio; los directorios seleccionados incluyen sus descendientes recursivamente. No se permiten rutas absolutas, .. ni patrones glob. Las rutas inexistentes se ignoran. Las exclusiones predeterminadas siguen vigentes fuera de las rutas seleccionadas, y la lista efectiva aparece en los informes y se compara con las baselines.

Personalización por equipo: extends y rules ​

El vocabulario está tomado directamente de ESLint, porque es un vocabulario que la mayoría de equipos ya conoce:

  • rules sobrescribe la severidad de un check específico por ID: "HYG-05": "off". La severidad es "off" o "error" en esta versión — "error" es el default implícito de todo check, y "off" remueve el check del numerador y del denominador de la puntuación de su dimensión (se excluye estructuralmente, nunca cuenta como fallo). "warn" es un valor reconocido pero rechazado deliberadamente hoy con un error claro de "aún no soportado" — reservado para un modo futuro, consultivo y no bloqueante.
  • extends aplica un preset con nombre, curado por los maintainers — un paquete versionado y revisado vía PR de overrides de rules, no una excepción libre por repositorio. Esto preserva la misma gobernanza que ya protege el catálogo de checks: proponer un preset nuevo pasa por revisión (ver CONTRIBUTING.md), no es un opt-out local silencioso. Los presets en extends se aplican en el orden del array, y cualquier entrada explícita en rules siempre prevalece sobre un preset.

Todo check excluido por extends/rules siempre se divulga — en la salida de terminal (línea Preset: ...), en el reporte Markdown (línea **Preset:** y estado ➖ en la tabla de checks) y en el campo preset del --json — nunca escondido silenciosamente detrás de un flag.

Una excepción, a propósito: HYG-03, HYG-04 y HYG-06 — los checks que detectan credenciales activamente filtradas o expuestas — nunca pueden ponerse en "off", ni vía rules ni vía preset. Todo lo demás en este formato de config se apoya en divulgación y revisión de PR para mantener la integridad; estos tres son el único punto que no es negociable.

Presets nativos ​

PresetEfectoPor qué
no-hooksPone HKS-01–HKS-05 (toda la dimensión Hooks & Guardrails, 14 de 108 puntos) en "off"Para entornos donde ejecutar scripts de hook local está prohibido por política — dev containers bloqueados, orgs reguladas, runners compartidos sin permiso de instalar hooks. El guardrail en esos casos se aplica solo vía CI.

Excluir una dimensión entera tiene una consecuencia honesta que vale la pena saber de antemano: como L4 · Self-correcting está definido por hooks de guardrail en runtime (ver el Modelo de madurez), un repositorio bajo no-hooks nunca alcanza L4 — el nivel queda capped (limitado), no "reprobado". report.level.capped es true y report.level.capReason explica el motivo; el resto de dimensiones mantiene su puntuación intacta. Esto es el escáner siendo honesto sobre lo que "self-correcting" significa, no una penalización por excluir hooks.

Flags de CLI (configuración del scan) ​

El descubrimiento de maturity del repositorio no tiene límite de profundidad en producción. Incluye archivos tracked, untracked e ignored después de omitir directorios conocidos de dependencias y artefactos generados. file-count-limit representa un fusible de emergencia de 1.000.000 de archivos para el repositorio; los overlays limitados de user y extra roots aún pueden reportar depth-limit. Una ruta descubierta que no puede inspeccionarse cuando un check la solicita reporta unreadable-path; los contenidos de más de 512 KiB omitidos intencionalmente no reportan ese motivo. Los symlinks internos se siguen y deduplican; un destino fuera de la raíz reporta outside-root-symlink y no se recorre ni se lee.

FlagSignificado
--config <file>Cargar config desde ruta específica
--scope userHabilitar scope user (separados por coma: user, system)
--gate maturity|effectivePuntaje usado para --min-level
--min-level <0-4>Exit 1 cuando el puntaje gated completo está bajo el nivel; un snapshot seleccionado por el gate incompleto retorna exit 2
--jsonReporte completo incluyendo scopes, gate, effective y verdicts

Inputs de GitHub Action ​

InputDefaultSignificado
include-user-harnessfalsePasa --scope user
include-system-harnessfalsePasa --scope system
gatematurityPasa --gate
config''Pasa --config cuando está definido
min-level0Falla cuando el puntaje gated está bajo el nivel

Outputs: level, level-name, percent (maturity); effective-level, effective-percent. La Action publica outputs, badge y reporte de maturity solo cuando maturity está completo, y outputs de effective solo cuando effective está completo. Si solo effective está incompleto, gate: maturity puede pasar con una advertencia; gate: effective retorna exit 2. Maturity incompleto no publica outputs de maturity, badge, reporte o comentario en la PR.

Campos JSON del reporte (estables) ​

CampoDescripción
rootRaíz absoluta del scan
scopes.maturitySiempre ["repo"]
scopes.effectiveej.: ["repo"], ["repo","user"]
gate"maturity" o "effective"
resolvedRootsLista opcional de { scope, absPath } para overlays
level, score, dimensions, checksSnapshot de maturity
effectiveMisma forma: { level, score, dimensions, checks, detectedHarnesses }
detectedHarnessesHerramientas vistas en el repo (informativo)
verdicts.maturity, verdicts.effectiveEstado de completitud y motivos deterministas de cada snapshot: complete o incomplete
verdicts.*.reasons[]file-count-limit, depth-limit, unreadable-directory, unreadable-path o outside-root-symlink, con path y limit opcionales
truncatedAlias de compatibilidad; true cuando el snapshot de maturity o effective está incompleto por cualquier motivo
preset{ extends, rules, resolved } — personalización de equipo efectivamente aplicada; resolved solo lista checks cuya severidad difiere del default
level.capped, level.capReasoncapped es true cuando un requisito bloqueante del siguiente nivel nunca puede cumplirse bajo la config actual (ej.: dimensión excluida por preset); capReason explica el motivo
dimensions[].applicablefalse cuando ningún check de esa dimensión entra en la puntuación: todo check está en "off" y/o checks[].applicable es false
checks[].applicablefalse cuando el check no aplica a este repositorio (HYG-05 con license de código cerrado, HYG-08 sin config MCP). Excluido del numerador y del denominador. El default es true. Omitido en reportes antiguos, lo que significa aplicable
checks[].severity"off" | "warn" | "error" — la severidad resuelta que este scan usó para ese check
checks[].warningsDiagnósticos opcionales y no fatales { code, message, source? }; terminal y Markdown los muestran sin cambiar puntos

level, score, dimensiones y checks siguen presentes para diagnóstico, pero son provisionales cuando su veredicto es incomplete. Terminal y Markdown identifican el snapshot no disponible. El badge siempre representa maturity y usa incomplete, nunca L0-L4, cuando maturity está incompleto. Los reportes antiguos sin verdicts se consideran completos cuando truncated es false e incompletos cuando es true.

--diff compara campos de maturity por defecto (top-level level / score / checks) y rechaza un baseline o resultado actual con maturity incompleto. Effective incompleto no bloquea un diff de maturity. Un check que pasa de aplicable a no aplicable (o al revés) es un delta propio (became-applicable / became-not-applicable), separado de newly passing o newly failing.