"""One-command end-to-end demo (plan §3): stock drop -> A2A hand-off -> negotiations -> best deal -> AP2 mandate -> human approves (dashboard or scripts/decide.py) -> PO write-back -> confirmation. Run: python -m scripts.run_demo [--sku SEED-MAIZE-01] [--auto-approve] """ from __future__ import annotations import argparse import asyncio import json import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from core.events import EventBus # noqa: E402 from orchestrator.gate import run_gate # noqa: E402 from orchestrator.pipeline import run_pipeline # noqa: E402 async def main() -> None: parser = argparse.ArgumentParser() parser.add_argument("--sku", default=None) parser.add_argument("--auto-approve", action="store_true", help="testing only: approve without a human (CI/self-test)") parser.add_argument("--run-id", default=None, help="fix the run id (the dashboard uses this to follow live)") parser.add_argument("--live-lock-token", default=None, help=argparse.SUPPRESS) args = parser.parse_args() bus = EventBus(args.run_id) print(f"[demo] run_id = {bus.run_id}") print(f"[demo] events -> traces/{bus.run_id}.jsonl") try: result = await run_pipeline(bus, sku=args.sku) finally: # The shared provider slot protects only the API-heavy pipeline. Once # the mandate exists, each visitor can wait at their own human gate. if args.live_lock_token: from core.hosted_runtime import release_live_slot release_live_slot(args.live_lock_token) if result["status"] != "winner_selected": print(f"[demo] pipeline ended early: {result['status']}") return if args.auto_approve: from core.config import traces_dir (traces_dir() / f"{bus.run_id}.decision.json").write_text( json.dumps({"decision": "approve"}), encoding="utf-8") print("[demo] waiting at the human gate — open the dashboard " "(streamlit run ui/app.py) or run: python -m scripts.decide " f"--run {bus.run_id} approve") outcome = await run_gate(bus, result) print(f"[demo] outcome: {json.dumps(outcome, indent=2)}") if __name__ == "__main__": asyncio.run(main())