claude-code-arcane 2.0.0 → 2.2.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +6 -4
  3. package/agents/audio/audio-director.md +90 -0
  4. package/agents/audio/audio-programmer.md +97 -0
  5. package/agents/audio/audio-qa.md +95 -0
  6. package/agents/audio/composer.md +88 -0
  7. package/agents/audio/technical-sound-designer.md +90 -0
  8. package/agents/audio/voice-director.md +96 -0
  9. package/docs/SKILLS-CATALOG.md +45 -2
  10. package/docs/USER-GUIDE.md +2 -2
  11. package/package.json +1 -1
  12. package/profiles/audio.yaml +45 -0
  13. package/profiles/second-brain.yaml +37 -0
  14. package/rules/gamedev/audio-code.md +45 -0
  15. package/rules/vault-conventions.md +144 -0
  16. package/skills/adaptive-music/SKILL.md +171 -0
  17. package/skills/adaptive-music/references/anti-patterns.md +53 -0
  18. package/skills/audio-audit/SKILL.md +164 -0
  19. package/skills/audio-audit/references/anti-patterns.md +65 -0
  20. package/skills/audio-audit/scripts/check_assets.py +208 -0
  21. package/skills/audio-bible/SKILL.md +119 -0
  22. package/skills/audio-bible/references/anti-patterns.md +39 -0
  23. package/skills/audio-mix/SKILL.md +151 -0
  24. package/skills/audio-mix/references/anti-patterns.md +65 -0
  25. package/skills/audio-spec/SKILL.md +107 -0
  26. package/skills/audio-spec/references/anti-patterns.md +45 -0
  27. package/skills/brain-dump/SKILL.md +53 -0
  28. package/skills/hub-note/SKILL.md +68 -0
  29. package/skills/middleware-integration/SKILL.md +186 -0
  30. package/skills/middleware-integration/references/anti-patterns.md +69 -0
  31. package/skills/midi-compose/SKILL.md +136 -0
  32. package/skills/midi-compose/references/smf-format.md +129 -0
  33. package/skills/midi-compose/scripts/compose_midi.py +326 -0
  34. package/skills/midi-compose/templates/example-composition.json +69 -0
  35. package/skills/music-composition/SKILL.md +106 -0
  36. package/skills/music-composition/references/form.md +57 -0
  37. package/skills/music-composition/references/game-music.md +82 -0
  38. package/skills/music-composition/references/harmony.md +82 -0
  39. package/skills/music-composition/references/melody.md +48 -0
  40. package/skills/music-composition/references/orchestration.md +69 -0
  41. package/skills/music-composition/references/rhythm-groove.md +49 -0
  42. package/skills/obsidian-bases/SKILL.md +85 -0
  43. package/skills/obsidian-bases/references/bases-syntax.md +123 -0
  44. package/skills/obsidian-canvas/SKILL.md +91 -0
  45. package/skills/obsidian-markdown/SKILL.md +110 -0
  46. package/skills/pdf-generator/scripts/fill_inspect.py +2 -0
  47. package/skills/pdf-generator/scripts/render_body.py +2 -0
  48. package/skills/procedural-audio/SKILL.md +157 -0
  49. package/skills/procedural-audio/references/anti-patterns.md +45 -0
  50. package/skills/review-dump/SKILL.md +108 -0
  51. package/skills/review-monthly/SKILL.md +56 -0
  52. package/skills/review-weekly/SKILL.md +91 -0
  53. package/skills/second-brain/SKILL.md +211 -0
  54. package/skills/second-brain/hooks/hooks.json +16 -0
  55. package/skills/second-brain/hooks/validate-note.sh +85 -0
  56. package/skills/second-brain/references/cross-project.md +57 -0
  57. package/skills/second-brain/references/templates/Atomic.md +22 -0
  58. package/skills/second-brain/references/templates/Daily.md +25 -0
  59. package/skills/second-brain/references/templates/Dashboard.base +70 -0
  60. package/skills/second-brain/references/templates/Dump.md +11 -0
  61. package/skills/second-brain/references/templates/Hub.md +22 -0
  62. package/skills/second-brain/references/templates/Monthly.md +29 -0
  63. package/skills/second-brain/references/templates/Weekly.md +29 -0
  64. package/skills/second-brain/references/templates/codebases.md +37 -0
  65. package/skills/second-brain/references/templates/hot.md +37 -0
  66. package/skills/second-brain/references/templates/vault-CLAUDE.md +127 -0
  67. package/skills/sfx-design/SKILL.md +130 -0
  68. package/skills/sfx-design/references/anti-patterns.md +53 -0
  69. package/skills/spatial-audio/SKILL.md +139 -0
  70. package/skills/spatial-audio/references/anti-patterns.md +53 -0
  71. package/skills/ui-sound-design/SKILL.md +133 -0
  72. package/skills/ui-sound-design/references/anti-patterns.md +57 -0
  73. package/skills/vault-audit/SKILL.md +72 -0
  74. package/skills/vault-audit/scripts/vault_audit.py +539 -0
  75. package/skills/vault-clip/SKILL.md +73 -0
  76. package/skills/vault-recall/SKILL.md +82 -0
  77. package/skills/vault-recall/scripts/vault_index.py +626 -0
  78. package/skills/vault-tidy/SKILL.md +76 -0
  79. package/skills/voice-pipeline/SKILL.md +150 -0
  80. package/skills/voice-pipeline/references/anti-patterns.md +69 -0
  81. package/skills/xlsx-generator/scripts/formula_check.py +2 -0
  82. package/skills/xlsx-generator/scripts/libreoffice_recalc.py +2 -0
  83. package/skills/xlsx-generator/scripts/xlsx_add_column.py +2 -0
  84. package/skills/xlsx-generator/scripts/xlsx_insert_row.py +2 -0
  85. package/skills/xlsx-generator/scripts/xlsx_reader.py +2 -0
  86. package/skills/zettel/SKILL.md +66 -0
@@ -0,0 +1,164 @@
1
+ ---
2
+ name: audio-audit
3
+ description: "Auditoria de audio: voice count, CPU, memoria, streaming, compliance de loudness (ASWG-R001), conformidad de assets contra spec y checklist por plataforma. Usar para: QA de audio, performance de audio, verificar loudness, revisar assets, pre-certificacion."
4
+ category: "audio"
5
+ argument-hint: "[full | perf | loudness | assets | platform]"
6
+ user-invocable: true
7
+ allowed-tools: Read, Glob, Grep, Write, Edit, Bash
8
+ ---
9
+ # audio-audit — QA y Compliance de Audio
10
+
11
+ Verifica que el audio del proyecto cumple: performance dentro del presupuesto, assets conformes al spec, y loudness dentro del target de plataforma.
12
+
13
+ ## Cuándo usar
14
+
15
+ - Antes de una milestone o de certificación
16
+ - El audio se corta, se satura o come demasiado CPU
17
+ - Verificar assets entregados por un contractor
18
+ - Auditar loudness para cumplir requisitos de plataforma
19
+ - Después de integrar un sistema nuevo, para medir su costo real
20
+
21
+ ## Input
22
+
23
+ 1. Leer audio bible (sección 8, standards) y los specs de `/audio-spec`
24
+ 2. Determinar plataformas target, y cuál es la más baja
25
+ 3. Preguntar al usuario: alcance (`full` / solo perf / solo loudness / solo assets) y si hay captura de profiler disponible
26
+
27
+ ---
28
+
29
+ ## 1. Performance
30
+
31
+ **Presupuesto:** el audio dispone del **5-10% del frame time**. A 60 fps el frame son 16.6 ms, así que el audio tiene ~0.8-1.7 ms. A 90 fps (VR) el frame son ~11 ms y el margen es menor.
32
+
33
+ | Métrica | Cómo se mide | Verdict |
34
+ |---|---|---|
35
+ | **CPU de audio** | Profiler del middleware, en gameplay real | FAIL si supera el 10% del frame sostenido |
36
+ | **Voces activas** | Pico vs límite configurado | CONCERNS si el pico toca el límite; FAIL si hay descartes de sonidos de prioridad alta |
37
+ | **Memoria de audio** | Por bank y total, vs budget del proyecto | FAIL si supera el budget en la plataforma más baja |
38
+ | **Accesos de streaming** | Contador de streaming del profiler | CONCERNS si hay starvation |
39
+ | **Game objects registrados** | Contador, medido a lo largo de una sesión larga | FAIL si crece monótonamente (leak) |
40
+
41
+ **Medir en gameplay real, no en el editor.** El editor dispara eventos en orden, uno por vez, sin ruido. El jugador produce combinaciones que nadie planificó. Y medir en la **plataforma más baja** del target: el presupuesto que cierra en PC no dice nada de un handheld.
42
+
43
+ **El leak de game objects es el hallazgo más frecuente.** Si el contador de objetos registrados crece durante una sesión de dos horas y nunca baja, hay des-registros faltantes. Se ve solo en sesiones largas.
44
+
45
+ ### Costos de referencia
46
+
47
+ Para saber si un número medido es razonable:
48
+
49
+ | Operación | Costo esperado por fuente |
50
+ |---|---|
51
+ | Convolución HRTF (512 taps) | ~2 ms |
52
+ | Encode ambisónico | ~0.1 ms |
53
+ | Decode ambisónico a binaural | ~1 ms total |
54
+ | Footstep procedural | ~1-2 ms |
55
+ | Síntesis de viento | ~0.5 ms/frame |
56
+ | Panning + atenuación | despreciable |
57
+
58
+ Si lo medido se desvía mucho del esperado, la causa suele ser configuración (más taps, más fuentes espacializadas de las previstas) antes que el motor.
59
+
60
+ ## 2. Loudness
61
+
62
+ Referencia de industria en juegos: **ASWG-R001** (Sony), la única especificación publicada por una plataforma mayor.
63
+
64
+ | Contexto | Loudness promedio | True peak máximo |
65
+ |---|---|---|
66
+ | Consola / home | **−23 LUFS** (±2) | **−1 dBTP** |
67
+ | Portable / handheld | **−18 LUFS** | −1 dBTP |
68
+
69
+ **Cómo medir bien:**
70
+
71
+ - Se mide el **programa completo en gameplay representativo**, no un asset aislado. Medir un `.wav` no dice nada sobre cumplimiento
72
+ - Sesión de duración suficiente para promediar: al menos varios minutos cubriendo exploración, combate y diálogo
73
+ - Medir el **true peak**, no el peak de sample: la codificación lossy puede generar picos por encima del valor medido en PCM
74
+ - **Confirmar el target vigente** de cada plataforma antes de certificación. Las recomendaciones se revisan — el promedio de ASWG también se citó como −24 LKFS, así que no confiar en un número memorizado
75
+
76
+ **Verdict:** COMPLIANT dentro del target con su tolerancia; NON-COMPLIANT fuera, o con true peak por encima de −1 dBTP.
77
+
78
+ ## 3. Conformidad de assets
79
+
80
+ Verificación mecánica contra los standards del bible. Esto se automatiza:
81
+
82
+ | Chequeo | Falla típica |
83
+ |---|---|
84
+ | Sample rate | Mezcla de 44.1 y 48 kHz en el mismo proyecto |
85
+ | Bit depth | 24-bit donde el pipeline espera 16 |
86
+ | Canales | Estéreo en un asset que se usa como fuente 3D mono |
87
+ | Naming | No sigue el patrón; rompe batch y automatización de banks |
88
+ | DC offset | Produce clicks al concatenar |
89
+ | Silencio al inicio | Retrasa el ataque; se percibe como lag |
90
+ | Clipping | Picos a 0 dBFS en el asset crudo |
91
+ | Duración vs spec | Fuera del rango especificado |
92
+ | Loudness por categoría | Assets de la misma categoría con niveles dispares |
93
+
94
+ **Fuente 3D en estéreo es el hallazgo más común y el más silencioso:** el middleware la trata distinto o la colapsa, y la localización espacial se degrada sin que nadie vea un error.
95
+
96
+ La skill trae el verificador: `scripts/check_assets.py`, stdlib-only (módulo `wave`), recursivo sobre una carpeta.
97
+
98
+ ```bash
99
+ python skills/audio-audit/scripts/check_assets.py assets/audio \
100
+ --rate 48000 --bits 16 --mono-3d --naming '^(sfx|vo|mus)_'
101
+ ```
102
+
103
+ Chequea sample rate, bit depth, canales, naming, clipping, DC offset, silencio inicial, archivos vacíos o silenciosos, y avisa cuando el sample rate obliga a un resampleo costoso. Emite `[FAIL]` / `[WARN]` / `[SKIP]` por hallazgo y cierra con COMPLIANT / CONCERNS / NON-COMPLIANT; exit code 1 solo si hay FAIL, para usarlo en CI.
104
+
105
+ Lo que necesita una herramienta externa (loudness integrado, análisis espectral) se reporta como `[SKIP]` en vez de abortar la corrida.
106
+
107
+ ## 4. Checklist por plataforma
108
+
109
+ | Ítem | Aplica a |
110
+ |---|---|
111
+ | Loudness dentro del target del contexto | Todas |
112
+ | True peak ≤ −1 dBTP | Todas |
113
+ | Manejo de interrupciones (llamada, alarma) | Móvil |
114
+ | Manejo de cambio de ruta (auriculares) | Móvil, consola |
115
+ | Respeto del switch de silencio | iOS |
116
+ | Comportamiento en background | Móvil |
117
+ | Mezcla con audio de terceros | Móvil |
118
+ | Audio no rompe al perder foco | Todas |
119
+ | Memoria dentro del budget de la plataforma | Todas |
120
+ | Se puede mutear todo desde opciones | Todas |
121
+ | Controles separados: música / SFX / voz / UI | Todas |
122
+ | Información crítica no exclusivamente por audio | Todas (accesibilidad) |
123
+ | Subtítulos para todo el diálogo | Todas (accesibilidad) |
124
+
125
+ El comportamiento en background y el switch de silencio en iOS son causas concretas de rechazo de store, no recomendaciones.
126
+
127
+ ---
128
+
129
+ ## Proceso
130
+
131
+ 1. **Determinar el alcance** y la plataforma más baja del target
132
+ 2. **Capturar** con el profiler del middleware en gameplay representativo, no en el editor
133
+ 3. **Medir performance** contra el presupuesto y comparar con los costos de referencia
134
+ 4. **Medir loudness** del programa completo, con true peak
135
+ 5. **Verificar assets** contra los standards, automatizado si el volumen lo justifica
136
+ 6. **Recorrer el checklist** de plataforma
137
+ 7. **Reportar** con severidad por hallazgo y, si el usuario lo pide, preguntar "¿Escribo el reporte a `<path>`?" antes de usar Write
138
+
139
+ ### Formato del reporte
140
+
141
+ Por hallazgo: qué se midió, valor medido, valor esperado, severidad, y dónde está el problema. Un hallazgo sin número medido no es un hallazgo, es una impresión.
142
+
143
+ ---
144
+
145
+ ## Verdict
146
+
147
+ Global, y por sección:
148
+
149
+ - **COMPLIANT** — performance dentro del presupuesto en la plataforma más baja, loudness dentro del target, assets conformes, checklist completo
150
+ - **CONCERNS** — hay desvíos que no bloquean: pico de voces tocando el límite, assets con naming inconsistente, loudness en el borde de la tolerancia
151
+ - **NON-COMPLIANT** — CPU o memoria fuera de presupuesto, loudness fuera del target, leak de game objects, o un ítem de checklist que es causa de rechazo de plataforma
152
+
153
+ Un NON-COMPLIANT en cualquier sección bloquea certificación.
154
+
155
+ ## Anti-patterns
156
+
157
+ > → Read references/anti-patterns.md
158
+
159
+ ## Next steps
160
+
161
+ - `/spatial-audio` si el costo de espacialización está fuera de presupuesto
162
+ - `/audio-mix` si el problema es loudness o balance entre categorías
163
+ - `/middleware-integration` si hay leaks, banks mal organizados o descartes de voces
164
+ - `/procedural-audio` si la memoria no cierra por cantidad de samples
@@ -0,0 +1,65 @@
1
+ # Audio Audit — Anti-patterns
2
+
3
+ ## Medir en el editor
4
+
5
+ El editor dispara eventos en orden, uno por vez, sin ruido de fondo. El jugador produce combinaciones que nadie planificó. Las mediciones del editor no predicen nada.
6
+
7
+ ## Medir en la plataforma más alta
8
+
9
+ El presupuesto cierra cómodo en PC y revienta en el handheld. La auditoría se hace contra el piso del target.
10
+
11
+ ## Medir loudness de un asset
12
+
13
+ Los targets de LUFS son del programa completo en gameplay representativo. Medir un `.wav` no dice nada sobre cumplimiento.
14
+
15
+ ## Sesión de medición demasiado corta
16
+
17
+ Treinta segundos de exploración tranquila da un LUFS que no representa el juego. La medición tiene que cubrir exploración, combate y diálogo.
18
+
19
+ ## Confiar en un target memorizado
20
+
21
+ Las recomendaciones de plataforma se revisan. Confirmar el vigente antes de certificación.
22
+
23
+ ## Medir peak de sample en vez de true peak
24
+
25
+ Un mix que llega a 0 dBFS en PCM puede generar picos por encima al codificarse en lossy. El −1 dBTP existe justamente por eso.
26
+
27
+ ## No buscar leaks
28
+
29
+ El contador de game objects registrados que crece durante dos horas y nunca baja es el hallazgo más frecuente, y solo se ve en sesiones largas. Una prueba de cinco minutos no lo encuentra.
30
+
31
+ ## Aceptar el pico de voces al límite
32
+
33
+ Si el pico toca el límite configurado, cualquier situación un poco peor empieza a descartar sonidos. Y si lo que se descarta es feedback de la acción del jugador, el juego se siente roto sin ningún error visible.
34
+
35
+ ## Ignorar qué se descarta
36
+
37
+ El número de descartes por sí solo no dice nada. Lo que importa es la prioridad de lo descartado: perder un ambiente lejano está bien, perder el disparo del jugador no.
38
+
39
+ ## Fuente 3D en estéreo
40
+
41
+ El hallazgo más silencioso: el middleware la colapsa o la trata distinto, y la localización espacial se degrada sin que aparezca ningún error. Verificar canales por categoría de uso.
42
+
43
+ ## Mezcla de sample rates
44
+
45
+ 44.1 y 48 kHz en el mismo proyecto obliga a resampleo en runtime, que cuesta CPU y puede introducir artefactos. Un solo sample rate por proyecto.
46
+
47
+ ## Silencio al inicio del asset
48
+
49
+ Retrasa el ataque y se percibe como lag de input, aunque el código responda instantáneo. Se detecta automáticamente y casi nunca se busca.
50
+
51
+ ## Hallazgo sin número
52
+
53
+ "El audio suena saturado" no es un hallazgo. Qué se midió, valor medido, valor esperado, dónde. Sin eso, nadie puede arreglarlo ni verificar que se arregló.
54
+
55
+ ## Auditar a mano miles de assets
56
+
57
+ La conformidad de sample rate, canales, naming y duración es mecánica: se automatiza. La inspección manual de 4.000 archivos garantiza que algo se pase por alto.
58
+
59
+ ## Fallar cuando falta una herramienta externa
60
+
61
+ Si el chequeo profundo necesita una herramienta que no está instalada, reportar `[SKIP]` y seguir. Abortar la auditoría entera por una dependencia opcional deja al usuario sin los chequeos que sí se podían correr.
62
+
63
+ ## Dejar el checklist de plataforma para el final
64
+
65
+ El comportamiento en background y el switch de silencio en iOS son causas concretas de rechazo. Descubrirlos en certificación cuesta una release.
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env python3
2
+ """Verifica conformidad mecanica de assets WAV contra los standards del proyecto.
3
+
4
+ Solo stdlib: usa el modulo `wave` para leer cabeceras y frames. Los chequeos que
5
+ necesitarian una herramienta externa se reportan como [SKIP], no rompen la corrida.
6
+
7
+ Uso:
8
+ python check_assets.py assets/audio
9
+ python check_assets.py assets/audio --rate 48000 --bits 16
10
+ python check_assets.py assets/audio --mono-3d --naming "^(sfx|vo|mus)_"
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import os
17
+ import re
18
+ import struct
19
+ import sys
20
+ import wave
21
+
22
+ # Umbrales de deteccion. Explicitos para que se puedan discutir.
23
+ LEADING_SILENCE_MS = 10.0 # silencio inicial que ya se percibe como lag
24
+ SILENCE_FLOOR = 0.002 # ~-54 dBFS: por debajo se considera silencio
25
+ DC_OFFSET_LIMIT = 0.01 # 1% de fondo de escala
26
+ CLIP_SAMPLE_LIMIT = 3 # muestras en fondo de escala para llamarlo clipping
27
+
28
+
29
+ class Finding:
30
+ __slots__ = ("path", "severity", "check", "detail")
31
+
32
+ def __init__(self, path: str, severity: str, check: str, detail: str):
33
+ self.path = path
34
+ self.severity = severity # FAIL | WARN | SKIP
35
+ self.check = check
36
+ self.detail = detail
37
+
38
+
39
+ def read_samples(handle: wave.Wave_read, limit: int | None = None) -> list[int]:
40
+ """Devuelve las muestras del primer canal, normalizadas a int con signo."""
41
+ width = handle.getsampwidth()
42
+ channels = handle.getnchannels()
43
+ frames = handle.getnframes() if limit is None else min(limit, handle.getnframes())
44
+ raw = handle.readframes(frames)
45
+
46
+ if width == 1:
47
+ # 8-bit WAV es unsigned; centrar en 0
48
+ values = [byte - 128 for byte in raw]
49
+ elif width == 2:
50
+ values = list(struct.unpack(f"<{len(raw) // 2}h", raw[: len(raw) // 2 * 2]))
51
+ elif width == 3:
52
+ values = []
53
+ for offset in range(0, len(raw) - 2, 3):
54
+ chunk = raw[offset:offset + 3]
55
+ value = int.from_bytes(chunk, "little", signed=True)
56
+ values.append(value)
57
+ elif width == 4:
58
+ values = list(struct.unpack(f"<{len(raw) // 4}i", raw[: len(raw) // 4 * 4]))
59
+ else:
60
+ return []
61
+
62
+ return values[::channels] if channels > 1 else values
63
+
64
+
65
+ def full_scale(width: int) -> float:
66
+ return float(2 ** (8 * width - 1))
67
+
68
+
69
+ def check_file(path: str, args: argparse.Namespace) -> list[Finding]:
70
+ findings: list[Finding] = []
71
+ name = os.path.basename(path)
72
+
73
+ if args.naming and not re.search(args.naming, name):
74
+ findings.append(Finding(path, "FAIL", "naming",
75
+ f"no matchea {args.naming!r}"))
76
+
77
+ try:
78
+ with wave.open(path, "rb") as handle:
79
+ rate = handle.getframerate()
80
+ width = handle.getsampwidth()
81
+ channels = handle.getnchannels()
82
+ frames = handle.getnframes()
83
+ duration = frames / rate if rate else 0.0
84
+
85
+ if args.rate and rate != args.rate:
86
+ findings.append(Finding(path, "FAIL", "sample-rate",
87
+ f"{rate} Hz, se esperaba {args.rate} Hz"))
88
+ if args.bits and width * 8 != args.bits:
89
+ findings.append(Finding(path, "FAIL", "bit-depth",
90
+ f"{width * 8}-bit, se esperaba {args.bits}-bit"))
91
+ if args.mono_3d and channels != 1:
92
+ findings.append(Finding(
93
+ path, "FAIL", "channels",
94
+ f"{channels} canales; una fuente 3D tiene que ser mono o el "
95
+ f"middleware la colapsa y se degrada la localizacion"))
96
+ if args.rate and rate and rate != args.rate and args.rate % rate and rate % args.rate:
97
+ findings.append(Finding(path, "WARN", "resample",
98
+ f"{rate} Hz no es multiplo ni divisor de "
99
+ f"{args.rate} Hz: el resampleo es mas costoso"))
100
+ if frames == 0:
101
+ findings.append(Finding(path, "FAIL", "empty", "0 frames"))
102
+ return findings
103
+ if args.max_duration and duration > args.max_duration:
104
+ findings.append(Finding(path, "WARN", "duration",
105
+ f"{duration:.2f} s > {args.max_duration:.2f} s"))
106
+
107
+ samples = read_samples(handle)
108
+ if not samples:
109
+ findings.append(Finding(path, "SKIP", "content",
110
+ f"{width * 8}-bit no soportado por el lector stdlib"))
111
+ return findings
112
+
113
+ scale = full_scale(width)
114
+ peak = max(abs(value) for value in samples)
115
+
116
+ clipped = sum(1 for value in samples if abs(value) >= scale - 1)
117
+ if clipped >= CLIP_SAMPLE_LIMIT:
118
+ findings.append(Finding(path, "FAIL", "clipping",
119
+ f"{clipped} muestras en fondo de escala"))
120
+
121
+ offset = sum(samples) / len(samples) / scale
122
+ if abs(offset) > DC_OFFSET_LIMIT:
123
+ findings.append(Finding(path, "WARN", "dc-offset",
124
+ f"{offset * 100:+.2f}% - produce clicks al concatenar"))
125
+
126
+ floor = SILENCE_FLOOR * scale
127
+ if peak < floor:
128
+ # Archivo enteramente silencioso: el chequeo de silencio inicial
129
+ # sobra, seria el mismo hallazgo dos veces.
130
+ findings.append(Finding(path, "FAIL", "silent", "el archivo es silencio"))
131
+ return findings
132
+
133
+ leading = 0
134
+ for value in samples:
135
+ if abs(value) > floor:
136
+ break
137
+ leading += 1
138
+ leading_ms = leading / rate * 1000
139
+ if leading_ms > LEADING_SILENCE_MS:
140
+ findings.append(Finding(
141
+ path, "WARN", "leading-silence",
142
+ f"{leading_ms:.1f} ms de silencio inicial - se percibe como lag de input"))
143
+
144
+ except wave.Error as error:
145
+ findings.append(Finding(path, "SKIP", "format",
146
+ f"no es un WAV PCM legible ({error})"))
147
+ except OSError as error:
148
+ findings.append(Finding(path, "FAIL", "io", str(error)))
149
+
150
+ return findings
151
+
152
+
153
+ def main(argv: list[str] | None = None) -> int:
154
+ parser = argparse.ArgumentParser(
155
+ description="Verifica conformidad de assets WAV contra los standards del proyecto.")
156
+ parser.add_argument("root", help="carpeta a auditar (recursivo)")
157
+ parser.add_argument("--rate", type=int, help="sample rate esperado, ej 48000")
158
+ parser.add_argument("--bits", type=int, choices=(8, 16, 24, 32),
159
+ help="bit depth esperado")
160
+ parser.add_argument("--mono-3d", action="store_true",
161
+ help="exigir mono (assets usados como fuentes 3D)")
162
+ parser.add_argument("--naming", help="regex que el nombre de archivo debe matchear")
163
+ parser.add_argument("--max-duration", type=float,
164
+ help="duracion maxima en segundos")
165
+ args = parser.parse_args(argv)
166
+
167
+ if not os.path.isdir(args.root):
168
+ print(f"[FAIL] no es una carpeta: {args.root}", file=sys.stderr)
169
+ return 1
170
+
171
+ paths = []
172
+ for directory, _subdirs, files in os.walk(args.root):
173
+ for name in sorted(files):
174
+ if name.lower().endswith(".wav"):
175
+ paths.append(os.path.join(directory, name))
176
+
177
+ if not paths:
178
+ print(f"[SKIP] no hay .wav en {args.root}")
179
+ return 0
180
+
181
+ findings: list[Finding] = []
182
+ for path in paths:
183
+ findings.extend(check_file(path, args))
184
+
185
+ fails = [f for f in findings if f.severity == "FAIL"]
186
+ warns = [f for f in findings if f.severity == "WARN"]
187
+ skips = [f for f in findings if f.severity == "SKIP"]
188
+
189
+ for group in (fails, warns, skips):
190
+ for finding in group:
191
+ relative = os.path.relpath(finding.path, args.root)
192
+ print(f"[{finding.severity}] {relative}: {finding.check} - {finding.detail}")
193
+
194
+ print()
195
+ print(f"{len(paths)} assets | {len(fails)} FAIL | {len(warns)} WARN | {len(skips)} SKIP")
196
+
197
+ if fails:
198
+ print("NON-COMPLIANT")
199
+ return 1
200
+ if warns:
201
+ print("CONCERNS")
202
+ return 0
203
+ print("COMPLIANT")
204
+ return 0
205
+
206
+
207
+ if __name__ == "__main__":
208
+ sys.exit(main())
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: audio-bible
3
+ description: "Audio Bible authoring: sonic palette, emotional targets per game state, frequency allocation, mix hierarchy, audio standards. Usar para: direccion de audio, paleta sonora, identidad sonora del juego."
4
+ category: "audio"
5
+ argument-hint: "[full|core|standards]"
6
+ user-invocable: true
7
+ allowed-tools: Read, Glob, Grep, Write, Edit
8
+ ---
9
+ # audio-bible — Sonic Identity Specification
10
+
11
+ Define la identidad sonora del juego. Toda produccion de audio se gatea contra este documento — es el equivalente auditivo de `/art-bible`.
12
+
13
+ ## Cuándo usar
14
+
15
+ - Después de tener game concept aprobado, antes de producir un solo sonido
16
+ - Cuando necesitás estandarizar el criterio sonoro entre sound designers y compositores
17
+ - Antes de escribir specs de SFX (`/audio-spec`) o diseñar el sistema de música (`/adaptive-music`)
18
+
19
+ ## Input
20
+
21
+ 1. Leer game concept (elevator pitch, pilares, core fantasy) y art bible si existe
22
+ 2. Preguntar al usuario: scope (full bible / core secciones 1-4 / solo standards), plataformas target, y referencias sonoras (juegos, films, discos)
23
+ 3. Si ya existe audio bible: detectar secciones completas vs vacías, trabajar solo las incompletas
24
+
25
+ ---
26
+
27
+ ## Secciones del Audio Bible
28
+
29
+ ### Core (secciones 1-4) — definen el lenguaje sonoro
30
+
31
+ | # | Sección | Qué define | Criterio de calidad |
32
+ |---|---------|-----------|-------------------|
33
+ | 1 | **Sonic Identity Statement** | Regla sonora de 1 línea + 2-3 principios de soporte | Resuelve cualquier ambigüedad sonora. Cada principio ancla en un pilar del juego |
34
+ | 2 | **Emotional Targets por Game State** | Qué debe sentir el jugador en exploración, combate, tensión, victoria, menú | Cada estado auditivamente distinto sin mirar la pantalla |
35
+ | 3 | **Sonic Palette** | Fuentes y texturas: acústico vs sintético, orgánico vs procesado, época/lugar, vocabulario tímbrico | Un sonido nuevo se puede aceptar o rechazar leyendo esto |
36
+ | 4 | **Frequency Allocation** | Qué categoría es dueña de qué banda — evita masking antes de que exista el mix | Diálogo, música, SFX y ambiente no compiten por la misma banda |
37
+
38
+ ### Production (secciones 5-8) — reglas concretas
39
+
40
+ | # | Sección | Qué define |
41
+ |---|---------|-----------|
42
+ | 5 | **Mix Hierarchy** | Prioridad entre categorías, qué duckea a qué, qué nunca se pisa |
43
+ | 6 | **Music Direction** | Instrumentación, escalas/modos, tempo range, rol del silencio, estrategia adaptativa |
44
+ | 7 | **SFX Direction** | Filosofía de impacto, realismo vs estilización, tratamiento del feedback de UI, uso de variación |
45
+ | 8 | **Audio Standards** | Sample rate, bit depth, formatos, naming, targets de loudness, budgets de memoria y voces por plataforma |
46
+
47
+ ### Reference (sección 9)
48
+
49
+ | # | Sección | Qué define |
50
+ |---|---------|-----------|
51
+ | 9 | **References & Prohibitions** | 3-5 referencias con qué tomar y qué evitar de cada una. Prohibiciones sonoras explícitas |
52
+
53
+ ---
54
+
55
+ ## Frequency allocation — el punto que más se saltea
56
+
57
+ La mayoría de los mixes de juego se rompen porque nadie asignó bandas antes de producir. Definir dueño primario por banda evita rehacer assets:
58
+
59
+ | Banda | Dueño primario | Nota |
60
+ |---|---|---|
61
+ | Sub (20-60 Hz) | Impactos, explosiones | Reservado, no lo llenes de música |
62
+ | Low (60-250 Hz) | Música (bajo, kick), body de impactos | Zona de masking más frecuente |
63
+ | Low-mid (250-500 Hz) | Ambiente, body de props | Acumula barro si no se controla |
64
+ | Mid (500 Hz-2 kHz) | **Diálogo** — intocable | El resto cede acá |
65
+ | High-mid (2-6 kHz) | Feedback de UI, transientes, definición | Fatiga rápido; usar con precisión |
66
+ | High (6-20 kHz) | Aire, detalle, brillo | Primero en irse en compresión lossy |
67
+
68
+ Cuando un asset nuevo pelea una banda que no le corresponde, la solución es de diseño (cambiar la fuente), no de EQ.
69
+
70
+ ---
71
+
72
+ ## Proceso
73
+
74
+ Para cada sección:
75
+ 1. **Draftar** basándose en game concept, pilares y referencias
76
+ 2. **Presentar** al usuario para review
77
+ 3. **Escribir** a archivo inmediatamente después de aprobación — preguntar "¿Escribo esta sección a `<path>`?" antes de usar Write
78
+
79
+ No batchear — escribir cada sección aprobada antes de pasar a la siguiente.
80
+
81
+ ### Conflictos
82
+
83
+ Si hay tensión entre dirección de audio y constraints técnicos (ej: música en stems para adaptatividad, pero el budget de memoria no da), surfacear el conflicto explícitamente con ambas posiciones. No resolver silenciosamente.
84
+
85
+ Si la dirección sonora conflictúa con accesibilidad (ej: información crítica solo por audio), surfacear y dejar que el usuario decida.
86
+
87
+ ---
88
+
89
+ ## Principios
90
+
91
+ - El audio bible es un **documento de restricción**: narrows solution space en favor de coherencia sonora
92
+ - Cada sección debe conectar con los pilares del juego
93
+ - Específico > genérico: "dark and tense" no alcanza — decir la emoción exacta, la fuente tímbrica, el rango de frecuencia, un elemento sonoro que carga el mood
94
+ - Para cada referencia: qué tomar Y qué evitar
95
+ - El silencio es una decisión de diseño, no la ausencia de una — documentarlo
96
+ - Los standards deben ser producibles: un contractor externo debería poder entregar assets válidos sin briefing adicional
97
+
98
+ ---
99
+
100
+ ## Anti-patterns
101
+
102
+ > → Read references/anti-patterns.md for common mistakes to avoid
103
+
104
+ ## Verdict
105
+
106
+ Al cerrar el documento, emitir un verdict por sección:
107
+
108
+ - **READY** — la sección resuelve ambigüedades y es accionable para producción
109
+ - **CONCERNS** — está escrita pero es genérica o no ancla en pilares; listar qué falta
110
+ - **BLOCKED** — falta input upstream (game concept, plataformas, budget) que no se puede inventar
111
+
112
+ Si alguna sección Core (1-4) queda en BLOCKED, el bible no habilita producción todavía.
113
+
114
+ ## Next steps
115
+
116
+ - `/audio-spec` para bajar la dirección a spec sheets de SFX y event lists
117
+ - `/adaptive-music` para diseñar el sistema de música contra los emotional targets de la sección 2
118
+ - `/audio-mix` para implementar la mix hierarchy de la sección 5
119
+ - `/audio-audit` para verificar assets producidos contra los standards de la sección 8
@@ -0,0 +1,39 @@
1
+ # Audio Bible — Anti-patterns
2
+
3
+ ## Dirección vacía
4
+
5
+ **Síntoma:** "El juego suena oscuro e inmersivo."
6
+
7
+ Cualquier sonido pasa ese filtro, así que no filtra nada. Una statement útil excluye: "Todo suena grabado dentro de una habitación de concreto — nada nace limpio, todo tiene el cuarto encima." Eso rechaza el 90% de una library.
8
+
9
+ ## Paleta sin fuentes
10
+
11
+ Listar adjetivos (cálido, agresivo, etéreo) sin decir de dónde sale el sonido deja la decisión al sound designer, que es exactamente lo que el bible debería resolver. Nombrar fuentes: instrumentos, materiales, técnicas de grabación, cadenas de procesamiento.
12
+
13
+ ## Frequency allocation ausente
14
+
15
+ Se produce todo, se llega al mix, y diálogo compite con música y SFX en 500 Hz-2 kHz. La solución tardía es EQ quirúrgico que adelgaza todo. La solución temprana es asignar bandas antes de producir.
16
+
17
+ ## Copiar la referencia entera
18
+
19
+ "Suena como Hollow Knight" sin decir qué se toma produce pastiche. Para cada referencia: qué tomar y qué evitar explícitamente.
20
+
21
+ ## Emotional targets que no se distinguen
22
+
23
+ Si exploración y tensión comparten instrumentación, tempo y densidad, el jugador no lee el estado por audio. Test: describir los estados sin nombrarlos y ver si son distinguibles.
24
+
25
+ ## Standards no producibles
26
+
27
+ "Audio de alta calidad, sin artefactos" no es un standard. Sample rate, bit depth, formato por plataforma, naming pattern, target de loudness con tolerancia, headroom y budget de voces sí lo son.
28
+
29
+ ## El silencio sin documentar
30
+
31
+ Los juegos con mejor audio usan silencio deliberadamente. Si el bible no dice dónde y por qué, alguien va a llenar cada segundo con ambiente.
32
+
33
+ ## Ignorar la plataforma
34
+
35
+ Un bible que asume monitores de estudio falla en el speaker de un handheld o en earbuds bluetooth. Los targets de loudness y la allocation de frecuencias cambian por plataforma — documentar cuáles importan.
36
+
37
+ ## Bible que nadie gatea
38
+
39
+ Si no hay un paso de review que compare assets contra el bible, es decoración. Conectarlo con `/audio-audit` y hacerlo condición de entrega.