🎭 Theater & Live Performance · post-show feedback

Lobby Reaction Harvester

Lovable AI synthesizes emotional reactions so producers gauge impact; the Adamo bridge records the sequence and replays it on cue.

Witness· sandbox-verified replay
Section · Kernel

The move.

full primer →

Directors press record; the bridge captures joint state and control cues into a JSON take, labels it with Lovable AI, and replays the post-show feedback sequence on the robot at any speed.

Why this kernelRecord + replay is the right primitive for post-show feedback: Theater & Live Performance lives on repeatable sequences — a phrase, a scene, a camera move — and the whole workflow is capture once, edit, then re-perform on the robot with a scrubbable timeline.

Kernel
a read-only surface fed by prior sandbox artifacts (`public/adamo-smoke.json`, `public/adamo-take.json`, `public/adamo-publish.json`) — the app is a timeline of verified moments, not a live control panel
Drives the UI as
a scrollable timeline of sandbox-verified events with timestamps, latency, and an inline JSON viewer for each take
Appendix · Setup

Run the bridge first.

ADAMO_API_KEY
On your laptop only — export it before starting the bridge. Never add it to Lovable secrets; the browser never sees it. Get one from operate.adamohq.com.
open ↗
adamo-bridge.py
The tiny Python bridge the browser calls at http://localhost:7878. Download once, run before you paste the mega-prompt into Lovable.
download ↓

Start the bridge on your laptop before pasting the prompt below. The Lovable app never holds the Adamo key.

Appendix · Mega-prompt

The build prompt.

Paste into a fresh Lovable project. Make sure the bridge above is running first. read the bridge protocol →

Build "Lobby Reaction Harvester" as a ONE-SHOT Lovable build **from a phone**. The participant
has only 5 credits and only a mobile browser — this single message must ship a
working demo with zero follow-ups and zero laptop steps. Physical AI on Adamo.

CONCEPT
Lovable AI synthesizes emotional reactions so producers gauge impact; the Adamo bridge records the sequence and replays it on cue.
Discipline: theater (post-show feedback).
Kernel: Witness (sandbox-verified replay).
Why this kernel: Record + replay is the right primitive for post-show feedback: Theater & Live Performance lives on repeatable sequences — a phrase, a scene, a camera move — and the whole workflow is capture once, edit, then re-perform on the robot with a scrubbable timeline.

MOBILE-ONLY, SANDBOX-BACKED — READ THIS FIRST
Adamo's SDK is Python-only. Cloudflare Workers cannot import it. The
participant is on a phone; there is no laptop bridge. The ONLY place inside
this Lovable session where the SDK runs is the Linux build sandbox. So:
  - Every Adamo call happens in a Python script the agent runs ONCE at
    build time in the sandbox.
  - The script writes a JSON proof artifact into `public/` that the
    deployed mobile web app fetches at runtime.
  - The deployed app itself never imports adamo, never holds
    ADAMO_API_KEY, never opens a QUIC/Zenoh socket, never calls a
    server function that tries to.
  - The runtime robot performance happens later at the physical showcase,
    off-device. The mobile app AUTHORS, the sandbox VERIFIES, the operator
    PLAYS BACK.

SECRETS
Request `ADAMO_API_KEY` via the add-secret tool (format hint `ak_...`).
Never reference it in .ts/.tsx code, never in `import.meta.env`, never in
a `createServerFn` handler. It lives only in the sandbox process env.

BUDGET (5 CREDITS, ONE-SHOT)
- ONE TanStack Start app, one primary route (`src/routes/index.tsx`).
- ONE mobile-first surface (touch targets >=44px, thumb-reachable primary
  action, no hover-only affordances, no drag-only interactions).
- Lovable AI Gateway allowed for text (default `google/gemini-3-flash-preview`),
  called from a server fn.
- NO database, NO auth, NO Lovable Cloud, NO extra pages, NO tests.
- Libraries: template defaults + `ai` + `@ai-sdk/openai-compatible` + `zod`.

VERIFIED ADAMO SDK SURFACE (adamo >= 0.4.42)
  import adamo
  session = adamo.connect(api_key=os.environ["ADAMO_API_KEY"])
  session.put(key, payload_bytes)
  sub = session.subscribe(key, callback=fn)      # kwarg-only, NOT positional
  session.get(key, timeout_ms=5000)              # returns list[Sample]
  session.live_tokens("**/alive")                # discovery (returns live tokens)
  session.alive(token_key)                       # DECLARES a token; not discovery
  session.close()
Footguns: subscribe callback is kwarg-only; `alive()` declares, `live_tokens`
discovers; `connect` requires `api_key=` (keyword).

STEP 1 — SMOKE TEST (mandatory, every build)
Write this to `scripts/adamo_smoke.py` verbatim:

```python
"""Verify ADAMO_API_KEY from the Lovable sandbox and write proof to
public/adamo-smoke.json. Run once during the build."""
from __future__ import annotations
import json, os, sys, time, threading
from datetime import datetime, timezone
from pathlib import Path

OUT = Path(__file__).resolve().parent.parent / "public" / "adamo-smoke.json"
OUT.parent.mkdir(parents=True, exist_ok=True)

def write(p): OUT.write_text(json.dumps(p, indent=2) + "\n"); print(json.dumps(p))

def main() -> int:
    key = os.environ.get("ADAMO_API_KEY")
    if not key:
        write({"ok": False, "error": "ADAMO_API_KEY missing"}); return 2
    try:
        import adamo
    except Exception as e:
        write({"ok": False, "error": f"adamo import failed: {e!r}"}); return 2

    out = {"ok": False, "at": datetime.now(timezone.utc).isoformat(),
           "sdk_version": getattr(adamo, "__version__", "unknown"),
           "roundtrip_ms": None, "alive": [], "error": None}
    s = None
    try:
        t0 = time.time()
        s = adamo.connect(api_key=key)
        out["connect_ms"] = int((time.time() - t0) * 1000)

        k = f"lovable/smoke/{int(time.time()*1000)}"
        got = threading.Event(); seen = {}
        def on(sample):
            try: seen["v"] = json.loads(bytes(sample.payload).decode())
            except Exception: seen["v"] = None
            got.set()
        sub = s.subscribe(k, callback=on)
        time.sleep(0.2)
        sent = time.time()
        s.put(k, json.dumps({"ping": sent}).encode())
        if got.wait(3.0):
            out["roundtrip_ms"] = int((time.time() - sent) * 1000)
            out["ok"] = True; out["echo"] = seen.get("v")
        else:
            out["error"] = "roundtrip timeout"
        try: sub.undeclare()
        except Exception: pass
        try: out["alive"] = sorted({str(t) for t in (s.live_tokens("**/alive") or [])})
        except Exception as e: out["alive_error"] = repr(e)
    except Exception as e:
        out["error"] = f"{type(e).__name__}: {e}"
    finally:
        try:
            if s is not None: s.close()
        except Exception: pass
    write(out)
    return 0 if out["ok"] else 1

if __name__ == "__main__":
    sys.exit(main())
```

Then in the sandbox run:
    python -m pip install --no-cache-dir adamo
    python scripts/adamo_smoke.py

Commit the resulting `public/adamo-smoke.json`.

STEP 2 — KERNEL JOB (Witness)
SANDBOX JOB — smoke test only
The Witness kernel reads pre-existing sandbox artifacts. Run only the smoke
test at build time. The app renders `/adamo-smoke.json` plus any prior
`/adamo-take.json` or `/adamo-publish.json` files as a "verified in the
sandbox at HH:MM" timeline. No new sandbox script needed.

STEP 3 — MOBILE APP
- `src/routes/index.tsx` renders the Witness surface for "Lobby Reaction Harvester".
- Include an `<AdamoProof />` card that `fetch("/adamo-smoke.json")` on
  mount and shows: "Sandbox verified at HH:MM · Xms roundtrip · N tokens
  live". Empty state: "No proof yet — re-run scripts/adamo_smoke.py".
- Mobile-first layout: single column, 16-24px padding, primary CTA fixed
  or bottom-anchored within thumb reach. NO desktop-only grids as the
  main surface.
- Empty state copy when no robot is connected: "Your key is verified in
  the sandbox. The operator will replay this on the robot at the
  showcase." — never "start the bridge" or "install Python".
- Tailwind + shadcn. Editorial industrial look: gold accent, dark
  background, one strong headline, one primary action.
- Footer: "Built during the Physical AI & Creative Robotics Hackathon
  organised by StreetKode Fam during Indian Krump Festival 14".

BRAIN — Lovable AI Gateway (already provisioned, no key prompt)
```ts
// src/lib/ai-gateway.server.ts
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
export function gateway() {
  return createOpenAICompatible({
    name: "lovable",
    baseURL: "https://ai.gateway.lovable.dev/v1",
    headers: {
      "Lovable-API-Key": process.env.LOVABLE_API_KEY!,
      "X-Lovable-AIG-SDK": "vercel-ai-sdk",
    },
  });
}
```
Call `generateText` inside `createServerFn` handlers only.

DO / DON'T
| Do                                              | Don't                                          |
| ----------------------------------------------- | ---------------------------------------------- |
| Run adamo only in scripts/ (sandbox)            | `import adamo` from a server fn or route       |
| Read `/adamo-smoke.json` from the browser       | Read ADAMO_API_KEY from `import.meta.env`      |
| `session.subscribe(k, callback=fn)`             | `session.subscribe(k, fn)` (positional fails)  |
| `session.live_tokens("**/alive")` for discovery | `session.alive()` for discovery                |
| Design for a phone in portrait first            | Ship a desktop dashboard as the primary UI     |

SUCCESS
On first load on a phone, the participant sees the Witness surface for
"Lobby Reaction Harvester", the AdamoProof card shows a green "sandbox verified" line with
a real roundtrip number, and the primary action is reachable with the
thumb. That is the demo.
Appendix · Market

Market sizing.

TAM
$30B
global live performance and theater market
SAM
$1.8B
audience engagement and ticketing software
SOM
$75M
AI feedback analysis tools

Indicative figures for hackathon pitches — refine with your own research before raising.

See also

Adjacent entries.