Files
marcopan c3a3cb8da5 feat(replay): standalone reviewer-gate replay server on :5333
Reproduces the real reviewer UI for any recorded session, with no VPN/Pi/
Python/DWH. The server (node:http, zero deps) serves the built SPA and a
tiny SSE/REST shim that re-emits the reviewer gates captured in a Pi
transcript, in their original order, with the reviewer's real 3-Jul
choices shown as comparison badges.

- tools/replay/extract.mjs: extracts gates from one or many transcripts
  (session-id, file, or directory). Handles sessions split across resume
  re-entries by sorting on message timestamp and dropping unanswered
  gates. Reads the question from session_manifest.yaml, resolving the
  sessions dir from any workspace yaml (no hardcoded paths).
- tools/replay/server.mjs: same-origin :5333. SSE streams gates; POST
  /response advances the cursor and pushes info badges (scelta reale).
  POST /resume and the final "Ripeti/Esci" widget close the SSE so the
  browser EventSource reconnects (cursor resets, gate 1 re-emitted) — the
  replay is re-runnable any number of times. GET /sessions/:id/documents
  reads the real session files so GateArtifactBody resolves file-reference
  artifacts. Exit emits system_event {event:"session_exit"} to return to
  the landing.
- scripts/replay.sh: launcher (extract / build / run / all).
- tools/replay/README.md: data flow, commands, fidelity notes.
- .gitignore: ignore tools/replay/web/ (built artifact, like dist/).
2026-07-05 18:24:26 +02:00

71 lines
2.4 KiB
Bash

#!/usr/bin/env bash
# Replay a recorded ThothII reviewer session on http://localhost:5333, with no
# VPN/Pi/Python/DWH. The real frontend UI is served against a tiny SSE/REST shim
# that re-emits the reviewer gates captured in Pi transcripts.
#
# Usage:
# scripts/replay.sh # extract(default) + build(if missing) + run
# scripts/replay.sh extract [<session>] # (re)build replay.json for a session
# scripts/replay.sh build # (re)build the SPA bundle only
# scripts/replay.sh run # run only (assumes build + fixture present)
#
# <session> a session id (e.g. 2026-07-03-170732-fammi-…)
# a transcript file path
# a directory of transcripts (picks the dominant session)
# default: the 3-Jul 17:07 full session
#
# Examples:
# scripts/replay.sh extract 2026-07-03-132933-fammi-la-lista-dei-pazienti-che-negli-ul
# scripts/replay.sh run
#
# Env:
# PORT default 5333
#
# See tools/replay/README.md for the data flow.
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)"
PORT="${PORT:-5333}"
WEB_DIR="$HERE/tools/replay/web"
FIXTURE="$HERE/tools/replay/replay.json"
action="${1:-all}"
# Positional target for extract: shifts past the action word.
target="${2:-}"
do_extract() {
echo "→ extracting replay.json for ${target:-default session (3-Jul 17:07)}…"
node "$HERE/tools/replay/extract.mjs" "$target"
}
do_build() {
if [[ -d "$WEB_DIR" ]]; then
echo "→ $WEB_DIR exists, skipping build (use 'rm -rf $WEB_DIR' to force)"
return
fi
echo "→ building SPA bundle into $WEB_DIR (VITE_BACKEND_URL=http://localhost:$PORT)…"
(
cd "$HERE/frontend"
VITE_BACKEND_URL="http://localhost:$PORT" npx vite build --outDir ../tools/replay/web
)
}
do_run() {
[[ -f "$FIXTURE" ]] || { echo "✗ missing $FIXTURE — run: scripts/replay.sh extract"; exit 1; }
[[ -d "$WEB_DIR" ]] || { echo "✗ missing $WEB_DIR — run: scripts/replay.sh build"; exit 1; }
echo "→ starting replay server on :$PORT (Ctrl-C to stop)…"
PORT="$PORT" node "$HERE/tools/replay/server.mjs"
}
case "$action" in
extract) do_extract ;;
build) do_build ;;
run) do_run ;;
all)
[[ -f "$FIXTURE" ]] || do_extract
do_build
do_run
;;
*) echo "unknown action: $action"; echo "usage: $0 [extract|build|run|all]"; exit 2 ;;
esac