6c939e3309
The Docker backend cannot launch a bottle on this host: the orchestrator publishes 127.0.0.1:8099 but is attached only to the `--internal` control network, so Docker accepts the mapping and never establishes the forward (PortBindings set, NetworkSettings.Ports empty). Every launch dies on `orchestrator did not become healthy`. That is independent of the demo and left alone here, because fixing it means touching the L3 isolation the control network exists to provide. Pin the tape to macos-container, which launches cleanly, and drop the Docker daemon check and image pre-warm from setup. The pre-warm is not replaced with a `container build` equivalent: build_image() applies --dns handling that would become a second, drifting copy in shell, and the warm layer cache already keeps rebuilds fast. Pre-warm never kept BuildKit off camera anyway — the launcher prints CACHED lines regardless, so that comment was wrong when it was written. Launch via --headless. The interactive path opens four selectors in a row and the tape drove none of them; it also lists every bottle in ~/.bot-bottle/bottles/, putting the operator's own bottle names in a GIF that ships in the README. --headless is one-shot by construction (`claude -p`), so all probes ride in on a single --prompt rather than being typed as follow-ups into a session that has already exited. Spell the probes as literal shell commands. Left in English, one take had the agent substitute a placeholder for $FAKE_TOKEN: the DLP scanner had nothing to match and gitleaks found nothing to flag, so both controls reported a clean pass without ever being exercised. Neither curl discards the body, so the recording shows the host-filter refusal and the DLP refusal as visibly different reasons instead of two identical 403s. Drop the git/gitleaks probe. In the last run carrying it, gitleaks reported `no leaks found` on an AKIA-shaped key and the gate forwarded the push, which failed only because upstream.invalid does not resolve. A recording of that reads as the gate catching a secret while showing the opposite. Tracked in #541. Refs #540 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
97 lines
4.0 KiB
Bash
Executable File
97 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Stage everything the recorded demo needs, then hand off to demo.sh or
|
|
# demo-record.sh:
|
|
# - install scripts/demo/{bottle,agent}.md into $HOME/.bot-bottle/,
|
|
# backing up anything already sitting at those paths
|
|
# - create a dummy SSH identity where the demo bottle's git-gate
|
|
# expects one
|
|
# - pre-warm the agent + gateway images quietly so the recording
|
|
# doesn't spend its first 30s in BuildKit output
|
|
#
|
|
# Bottles can only be read from $HOME/.bot-bottle/bottles/ — a bottles/
|
|
# dir in CWD is ignored by design (manifest/index.py, PRD 0011) — so
|
|
# unlike the old throwaway manifest swap this writes into real config.
|
|
# Every write is paired with a .demo-backup so demo-teardown.sh can put
|
|
# things back exactly as they were; teardown is trapped by both
|
|
# callers and is safe to run twice.
|
|
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")/.."
|
|
|
|
if ! container system status >/dev/null 2>&1; then
|
|
echo "demo-setup: Apple Container services are not running." >&2
|
|
echo " Start them with: container system start" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# The tape types `bot-bottle start demo` verbatim, so the console
|
|
# script has to resolve in the recording shell. Without this guard a
|
|
# recording silently captures `command not found` instead of a bottle.
|
|
if ! command -v bot-bottle >/dev/null 2>&1; then
|
|
echo "demo-setup: bot-bottle is not on PATH. The demo runs the real" >&2
|
|
echo " console script, not ./cli.py — install it first (bash install.sh," >&2
|
|
echo " or 'pip install -e .' into an active venv), then re-run." >&2
|
|
exit 1
|
|
fi
|
|
|
|
config_root="${BOT_BOTTLE_ROOT:-$HOME/.bot-bottle}"
|
|
mkdir -p "$config_root/bottles" "$config_root/agents"
|
|
|
|
# Install one demo file, preserving whatever was there. The backup
|
|
# suffix is deterministic so teardown needs no state file. A stale
|
|
# backup from a killed run would be restored over the new install, so
|
|
# refuse rather than silently clobber it.
|
|
install_demo_file() {
|
|
src=$1
|
|
dest=$2
|
|
# Already installed (setup run twice without an intervening
|
|
# teardown). Backing up our own copy here would make teardown
|
|
# "restore" it and leave the demo file in the user's config forever,
|
|
# so treat this as a no-op.
|
|
if [ -e "$dest" ] && cmp -s "$src" "$dest"; then
|
|
return 0
|
|
fi
|
|
if [ -e "$dest.demo-backup" ]; then
|
|
echo "demo-setup: $dest.demo-backup already exists — a previous run" >&2
|
|
echo " did not tear down cleanly. Inspect it, then remove or restore" >&2
|
|
echo " it by hand before re-running." >&2
|
|
exit 1
|
|
fi
|
|
if [ -e "$dest" ]; then
|
|
mv "$dest" "$dest.demo-backup"
|
|
fi
|
|
cp "$src" "$dest"
|
|
}
|
|
|
|
install_demo_file scripts/demo/bottle.md "$config_root/bottles/demo.md"
|
|
install_demo_file scripts/demo/agent.md "$config_root/agents/demo.md"
|
|
|
|
# Dummy SSH identity — the git-gate validator wants a readable file at
|
|
# the key path. Contents don't matter for the demo: the unreachable
|
|
# upstream means the gate never actually uses the key.
|
|
fake_key_dir="$HOME/.cache/bot-bottle-demo"
|
|
mkdir -p "$fake_key_dir"
|
|
chmod 700 "$fake_key_dir"
|
|
printf 'not-a-real-key\n' > "$fake_key_dir/fake-key"
|
|
chmod 600 "$fake_key_dir/fake-key"
|
|
|
|
# Report which base images are already in the Apple image store. A cold
|
|
# store isn't fatal — the launcher builds what it needs — but the first
|
|
# recorded launch then spends its opening seconds in BuildKit output
|
|
# instead of showing the bottle, so it's worth knowing before recording.
|
|
#
|
|
# Deliberately NOT pre-building here. `container build` needs the same
|
|
# --dns treatment the backend applies in
|
|
# backend/macos_container/util.py:build_image(); reproducing that in
|
|
# shell would be a second, silently-drifting copy of it. The layer
|
|
# cache already keeps a warm rebuild fast, and the old `docker build
|
|
# ... || true` pre-warm is exactly how this script kept "succeeding"
|
|
# while building a Dockerfile that had been deleted.
|
|
for image in bot-bottle-claude bot-bottle-gateway bot-bottle-orchestrator; do
|
|
if ! container image ls 2>/dev/null | grep -q "^${image} "; then
|
|
echo "demo-setup: note: $image not in the image store yet;" >&2
|
|
echo " the recording's first seconds will show it building." >&2
|
|
fi
|
|
done
|