feat: hand recorder v1 (tap-to-build, overlay) — recorder steps 2-4
Tap-to-build hand recorder per docs/RECORDER.md. Correctness by construction: every
tap writes a known value into a known slot, emitting the canonical structured contract
(server normalize_structured() is the shape authority, so the client is best-effort).
- recorder.js: mount-agnostic module (mounts into any container -> overlay now,
standalone later, zero logic change). Pure buildStructured(state)->contract dict.
Card picker: sticky-suit-or-rank-first + x (unknown suit) + unknown-card; lock resets
per slot so it never bleeds between cards. Pre-fills from /session/data (stakes->blinds,
stack->hero, villains->seated). Per-street action entry, manual street advance.
- recorder.css: full-screen overlay using app theme tokens; floating launcher.
- index.html: overlay div + script + launcher (chat/session stays mounted underneath).
Validated end-to-end: JS core builds a hand (sticky/rainbow/unknown cards all correct)
-> POST /hands -> normalized -> /hand/{id} replay round-trips identically.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<title>Lyra Core Chat</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link rel="stylesheet" href="/recorder.css" />
|
||||
<!-- PWA -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
@@ -1245,5 +1246,28 @@
|
||||
});
|
||||
</script>
|
||||
<script src="/nav.js"></script>
|
||||
<!-- Hand recorder (overlay; chat/session stays mounted underneath) -->
|
||||
<div id="recorderOverlay" class="rec-overlay"></div>
|
||||
<script src="/recorder.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var btn = document.createElement("button");
|
||||
btn.id = "recLaunch";
|
||||
btn.textContent = "+ Hand";
|
||||
btn.title = "Record a hand";
|
||||
document.body.appendChild(btn);
|
||||
var overlay = document.getElementById("recorderOverlay");
|
||||
function close() { overlay.classList.remove("open"); overlay.innerHTML = ""; }
|
||||
btn.addEventListener("click", function () {
|
||||
overlay.innerHTML = "";
|
||||
overlay.classList.add("open");
|
||||
var sid = window.currentSession;
|
||||
window.Recorder.mount(overlay, {
|
||||
onClose: close,
|
||||
onSave: function (id) { close(); window.open("/hand/" + id, "_blank"); }
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user