Bump to v2.2.0: fix warning/bubble sounds, add klaxon, refresh docs

- index.html: fix playWarningSound (440→550 Hz, louder), fix playBubbleSound
  (audible volumes/durations), add looping klaxon sound (sawtooth wah-wah),
  stopKlaxon() on tap and state clear, bump VERSION to v2.2.0
- kao_tui.py: add klaxon to SOUNDS list, drop notify duration 5→2s for
  faster iteration; also include improved post() error reporting
- CLAUDE.md: add kao_tui.py to file structure, fix personality table
  (remove ˙▿˙ row not in aggregator), add klaxon to sound list
- README.md: add klaxon to sound list, update counts
- openapi.yaml: bump version to 2.2.0, add klaxon to sound enum

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-20 17:30:19 -06:00
parent a36fd7037a
commit 50e34b24c6
5 changed files with 53 additions and 31 deletions

View File

@@ -217,7 +217,7 @@
const emoteEl = document.getElementById("emote");
const messageEl = document.getElementById("message");
const POLL_INTERVAL = 2000;
const VERSION = "v2.1.0";
const VERSION = "v2.2.0";
// Sound system
let audioCtx = null;
@@ -254,9 +254,9 @@
}
function playWarningSound() {
// Soft double-beep
playTone(440, 0.15);
setTimeout(() => playTone(440, 0.15), 180);
// Two-tone warning beep - differentiated pitches
playTone(440, 0.2, "sine", 0.18);
setTimeout(() => playTone(550, 0.2, "sine", 0.18), 220);
}
function playCriticalSound() {
@@ -334,8 +334,8 @@
playTone(1047, 0.15, "sine", 0.1);
}
function playBubbleSound() {
playTone(400, 0.06, "sine", 0.06);
setTimeout(() => playTone(600, 0.04, "sine", 0.04), 40);
playTone(400, 0.15, "sine", 0.10);
setTimeout(() => playTone(650, 0.12, "sine", 0.08), 100);
}
function playFanfareSound() {
playTone(523, 0.1, "sine", 0.1);
@@ -364,9 +364,28 @@
}
}
// Klaxon — looping wah-wah horn, loops until manually stopped
let klaxonInterval = null;
function playKlaxonTick() {
playTone(500, 0.22, "sawtooth", 0.22);
setTimeout(() => playTone(380, 0.22, "sawtooth", 0.22), 230);
}
function startKlaxon() {
if (klaxonInterval) return;
playKlaxonTick();
klaxonInterval = setInterval(playKlaxonTick, 470);
}
function stopKlaxon() {
if (klaxonInterval) {
clearInterval(klaxonInterval);
klaxonInterval = null;
}
}
// Play sound by name
function playSoundByName(name) {
if (name === "alarm") { startAlarm(); return; }
if (name === "alarm") { startAlarm(); return; }
if (name === "klaxon") { startKlaxon(); return; }
const sounds = {
chime: playChimeSound,
alert: playAlertSound,
@@ -403,7 +422,8 @@
playSoundByName(customSound);
lastCustomSound = customSound;
} else if (!customSound) {
stopAlarm(); // stop any looping alarm
stopAlarm(); // stop any looping sounds
stopKlaxon();
lastCustomSound = null;
}
@@ -434,7 +454,8 @@
// Handle tap - enable sound and show reaction
document.body.addEventListener("click", () => {
stopAlarm(); // stop any looping alarm
stopAlarm(); // stop any looping sounds
stopKlaxon();
// Enable sound on first tap (browser autoplay policy)
if (!soundEnabled) {
soundEnabled = true;