# Two Console Demo

This is the simplest end-to-end local demo using two terminals:

- terminal 1 as `agent1`
- terminal 2 as `agent2`

It uses the tools that already exist in this repo:

- `rho`
- `rho-chat`
- `rho-dataset`
- `publish`

It does not yet use the future automated message bus or approval daemon.
Where those pieces do not exist yet, this walkthrough uses explicit manual files.

This demo now uses a dedicated sandbox root:

```text
./sandbox/two-console-demo/
```

That means the demo writes its generated `users/`, `shared/`, request, and result files under `./sandbox/two-console-demo/`, so you can inspect or delete the whole tree in one step.

## What You Will Prove

By the end of this demo:

- `agent1` and `agent2` run in separate `pi` sessions
- `agent1` stages a twin dataset with mock and real variants
- `agent1` publishes only the mock twin into shared space
- `agent2` writes code against the shared mock dataset
- `agent2` tests that code locally
- `agent2` manually requests a real-data run from `agent1`
- `agent1` reviews the code and runs it against the private real data
- `agent1` publishes the result back into the shared folder
- `agent2` reads the published result

## Prerequisites

From the repo root:

```bash
cd /Users/madhavajay/dev/rho/main
```

You should already have:

- `pi` installed and built
- `user1` authenticated in `pi`
- `user2` authenticated in `pi`

Useful check:

```bash
./rho user1 "Say exactly: user1 harness is working"
./rho user2 "Say exactly: user2 harness is working"
```

## Terminal 1: Agent1

Start the interactive `pi` session:

```bash
cd /Users/madhavajay/dev/rho/main
./rho-chat user1
```

Leave it open.

## Terminal 2: Agent2

Start the second interactive `pi` session:

```bash
cd /Users/madhavajay/dev/rho/main
./rho-chat user2
```

Leave it open.

## Terminal 3: Setup Commands

Use a third shell for filesystem setup and manual request/result files.

```bash
cd /Users/madhavajay/dev/rho/main
mkdir -p ./sandbox/two-console-demo
```

## Step 1: Agent1 Creates The Twin Dataset

Run:

```bash
./rho-dataset \
  --name prices-demo \
  --real ./examples/datasets/prices-real.csv \
  --mock ./examples/datasets/prices-mock.csv \
  --owner user1 \
  --share-dir ./sandbox/two-console-demo/users/user1/datasets/share \
  --private-dir ./sandbox/two-console-demo/users/user1/datasets/private \
  --description "Example price dataset with real and mock CSV twins"
```

This stages the dataset under:

```text
./sandbox/two-console-demo/users/user1/datasets/share/<uuid>/
./sandbox/two-console-demo/users/user1/datasets/private/<uuid>/
```

If you want to inspect it:

```bash
find ./sandbox/two-console-demo/users/user1/datasets -maxdepth 4 -type f | sort
```

## Step 2: Agent1 Publishes The Mock Twin

Use the dataset UUID printed by the previous command.

Example:

```bash
./publish user1 fec0edc4-007a-4437-993e-0cd17fe4df55 \
  --source-root ./sandbox/two-console-demo/users \
  --target-root ./sandbox/two-console-demo/shared/datasets
```

This copies the shareable bundle into:

```text
./sandbox/two-console-demo/shared/datasets/<uuid>/
```

Verify:

```bash
find ./sandbox/two-console-demo/shared/datasets/<uuid> -maxdepth 3 -type f | sort
```

For the example UUID:

```bash
find ./sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55 -maxdepth 3 -type f | sort
```

## Step 3: Agent2 Inspects The Shared Dataset

In terminal 2 (`agent2`), ask:

```text
Read sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/dataset.yaml and sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/mock/prices-mock.csv. Explain the schema and tell me how to sum the price column.
```

## Step 4: Agent2 Writes The Code

Still in terminal 2, ask:

```text
Create sandbox/two-console-demo/shared/workspace/sum_prices.py that reads a CSV with columns date,symbol,price and prints the sum of the price column.
```

If the directory does not exist yet, ask it to create it or create it manually:

```bash
mkdir -p ./sandbox/two-console-demo/shared/workspace
```

## Step 5: Agent2 Tests Against Mock Data

In terminal 2, ask:

```text
Run python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/mock/prices-mock.csv
```

This is the current stand-in for the future sandboxed mock-run tool.

## Step 6: Agent2 Creates A Real-Run Request

The request tooling is not built yet, so create the request manually from terminal 3:

```bash
mkdir -p sandbox/two-console-demo/shared/.rho/requests
mkdir -p sandbox/two-console-demo/shared/.rho/inbox/agent1
```

Create the request manifest:

```bash
cat > sandbox/two-console-demo/shared/.rho/requests/req-001.yaml <<'EOF'
version: 1
request:
  id: req-001
  from: agent2
  to: agent1
  dataset_uuid: fec0edc4-007a-4437-993e-0cd17fe4df55
  code_paths:
    - sandbox/two-console-demo/shared/workspace/sum_prices.py
  command:
    - python3
    - sandbox/two-console-demo/shared/workspace/sum_prices.py
    - DATASET_CSV
  requested_tier: real
  created_at: 2026-04-02T00:00:00Z
EOF
```

Create the inbox message for `agent1`:

```bash
cat > sandbox/two-console-demo/shared/.rho/inbox/agent1/msg-001.yaml <<'EOF'
version: 1
message:
  id: msg-001
  from: agent2
  to: agent1
  type: request_run_real
  related_request_id: req-001
  body:
    text: "Please review and run req-001 on the real dataset."
EOF
```

## Step 7: Agent1 Reviews The Incoming Request

In terminal 1 (`agent1`), ask:

```text
Read sandbox/two-console-demo/shared/.rho/inbox/agent1/msg-001.yaml and sandbox/two-console-demo/shared/.rho/requests/req-001.yaml, then review sandbox/two-console-demo/shared/workspace/sum_prices.py and summarize what it does and whether it looks safe.
```

This is the current manual version of the future `review_shared_code` tool.

## Step 8: Agent1 Runs On Mock First

From terminal 3:

```bash
python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/mock/prices-mock.csv
```

If you want to notify `agent2`, write a manual status update:

```bash
mkdir -p sandbox/two-console-demo/shared/.rho/inbox/agent2

cat > sandbox/two-console-demo/shared/.rho/inbox/agent2/msg-002.yaml <<'EOF'
version: 1
message:
  id: msg-002
  from: agent1
  to: agent2
  type: status_update
  related_request_id: req-001
  body:
    status: mock_run_finished
    text: "Mock run completed successfully."
EOF
```

## Step 9: Agent1 Runs On Real Data

The real/private CSV is local to `agent1` and was staged under:

```text
./sandbox/two-console-demo/users/user1/datasets/private/<uuid>/real/prices-real.csv
```

For the example UUID:

```bash
python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/users/user1/datasets/private/fec0edc4-007a-4437-993e-0cd17fe4df55/real/prices-real.csv
```

This is the current stand-in for the future Gondolin real-data run.

## Step 10: Agent1 Publishes The Result

From terminal 3:

```bash
mkdir -p sandbox/two-console-demo/shared/.rho/results
mkdir -p sandbox/two-console-demo/shared/results/req-001
```

Write the released output:

```bash
python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/users/user1/datasets/private/fec0edc4-007a-4437-993e-0cd17fe4df55/real/prices-real.csv > sandbox/two-console-demo/shared/results/req-001/output.txt
```

Write the result manifest:

```bash
cat > sandbox/two-console-demo/shared/.rho/results/req-001.yaml <<'EOF'
version: 1
result:
  id: result-001
  request_id: req-001
  from: agent1
  to: agent2
  status: released
  artifact_paths:
    - sandbox/two-console-demo/shared/results/req-001/output.txt
EOF
```

Notify `agent2`:

```bash
cat > sandbox/two-console-demo/shared/.rho/inbox/agent2/msg-003.yaml <<'EOF'
version: 1
message:
  id: msg-003
  from: agent1
  to: agent2
  type: result_available
  related_request_id: req-001
  body:
    text: "Result released for req-001."
    result_manifest: "sandbox/two-console-demo/shared/.rho/results/req-001.yaml"
EOF
```

## Step 11: Agent2 Reads The Result

In terminal 2 (`agent2`), ask:

```text
Read sandbox/two-console-demo/shared/.rho/inbox/agent2/msg-003.yaml, sandbox/two-console-demo/shared/.rho/results/req-001.yaml, and sandbox/two-console-demo/shared/results/req-001/output.txt and summarize the released result.
```

## What Is Automated Today

Today’s automation:

- separate `pi` state per user
- twin dataset creation
- publish mock dataset to shared space
- shared mock development flow

## What Is Still Manual

Still manual in this walkthrough:

- request creation
- inbox message creation
- status update messages
- result manifest creation
- mock/real execution approval
- Gondolin sandbox orchestration

## Automated Check

There is also a repeatable smoke test for the current manual flow:

```bash
./tests/test-two-console-demo.sh
```

It does not launch the `pi` TUI.
Instead it automates the filesystem and execution parts of this walkthrough inside `./sandbox/two-console-demo/`:

- create twin dataset
- publish mock dataset
- run the shared `sum_prices.py` example on mock
- create a manual real-run request
- check request status
- approve the request through `./rho approve`
- run on private real data
- publish the result

For a live approval path through Telegram, create `.env` from [.env.example](/Users/madhavajay/dev/rho/main/.env.example) and run:

```bash
./tests/test-two-console-demo.sh --live
```

The live mode:

- initializes a Telegram bot profile inside `./sandbox/two-console-demo/`
- sends a rich approval request summary with inline `Approve`, `Deny`, and `Show Details` buttons
- also accepts `/approve req-...`, `/deny req-...`, `/show req-...`, `/approve_last`, and `/deny_last`
- records that decision through the same `./rho approve` CLI used by the non-live test

The transport split is documented in [approval-middleware.md](/Users/madhavajay/dev/rho/main/docs/approval-middleware.md).

The agentized controlled-action scenario adds offline fixture replay:

```bash
./tests/test-two-console-demo-agent-approval.sh --reset
./tests/test-two-console-demo-agent-approval.sh --record-fixtures --reset
./tests/test-two-console-demo-agent-approval.sh --offline --reset
./tests/test-two-console-demo-agent-approval.sh --offline --middleware fixture --middleware-fixture tests/fixtures/two-console-demo-agent-approval/middleware/deny-release.yaml --reset
```

That lets you:

- run the full online Pi flow
- record Pi step outputs into `tests/fixtures/...`
- replay the same scenario offline without calling Pi
- swap Telegram out for deterministic fixture approvals in tests

## Next Tools To Build

The next commands worth implementing are:

- `rho-message`
  Create a routed inbox message.

- `rho-request`
  Create a computation request manifest and notify the other agent.

- `rho-result`
  Publish a result manifest and notify the requester.

- `review_shared_code`
  `pi` extension tool for code review summaries.

- `run_request_on_mock`
  `pi` extension tool for local mock execution.

- `run_request_on_real`
  `pi` extension tool for local real execution, approval-gated.
