# Testing Your Lobu Project

Use this checklist to prove the paths the user selected. Replace placeholders
with ids returned by Lobu; do not invent agent, connection, feed, Automation, or
event ids.

## Local runtime

Validate the authored project before booting it:

```bash
npx @lobu/cli@latest validate
npx @lobu/cli@latest run
```

Leave `lobu run` running. With the embedded database default, it creates and
selects the `local` context, applies the project to the embedded runtime, and
prints the authoritative Web UI URL. Open that exact URL and verify the expected
agent, connections, feeds, and Automations are visible. With an external
`DATABASE_URL`, authenticate and apply to that runtime explicitly instead of
using the `local` commands below.

From another terminal, verify local MCP connectivity:

```bash
npx @lobu/cli@latest memory health --context local
```

Send a harmless direct message through the Agent API. `--dry-run` prevents
side-effecting tool calls, while the prompt keeps the check independent of
tools:

```bash
npx @lobu/cli@latest chat "Reply with exactly LOCAL_E2E_OK. Do not call tools." \
  --context local --agent "<agent-id>" --dry-run --new
```

Require the streamed response to contain `LOCAL_E2E_OK`. If the user selected a
configured chat platform, send a separate DM or channel message through that
platform and verify the reply there; a successful direct API check does not
prove Slack, Telegram, or another platform works.

## Connector and feed

Discover the live ids and current state instead of copying ids from config:

```bash
npx @lobu/cli@latest memory exec \
  'export default async (_ctx, client) => ({ connections: await client.connections.list(), feeds: await client.feeds.list() });' \
  --context local
```

Before consent to access provider data, inspect only the installed catalog,
connection, auth-profile, and feed metadata. `lobu validate` already checks the
auth/config shape. Confirm the connection is active and its declared config
matches the installed catalog schema. Browser actions require a paired extension;
inspect its device metadata without invoking browser actions. Durable managed
OAuth and env-profile credentials stay at the gateway. Wait for consent before a
server-side feed dry-run, because that dry-run may read upstream provider data.

After the user explicitly approves provider-data access, dry-run a collected
feed server-side first:

```bash
npx @lobu/cli@latest memory exec \
  'export default async (_ctx, client) => client.feeds.trigger({ feed_id: Number("<feed-id>"), dry_run: true });' \
  --context local
```

A feed dry-run records the run but does not persist collected events, entities,
attachments, checkpoint changes, or feed sync state. It cannot undo an upstream
side effect performed by connector code. Inspect the run until it reaches a
terminal state with `client.feeds.get({ feed_id: Number("<feed-id>") })`. After
the dry-run is healthy and the user approves a real collection, trigger without
`dry_run`, then read the feed again and verify the expected event or entity
exists.

Source-readable feeds can be queried live independently of sync. Verify those with
`client.feeds.readMany({ reads: [{ feed_id: Number("<feed-id>") }] })`.
If the connector declares no feeds, as with some chat
integrations, skip feed verification and prove its inbound message path instead.

## Automations and resulting data

List configured Automations, then trigger each selected Automation by its returned
id:

```bash
npx @lobu/cli@latest memory exec \
  'export default async (_ctx, client) => client.automations.list();' \
  --context local

npx @lobu/cli@latest memory exec \
  'export default async (_ctx, client) => client.automations.trigger({ automation_id: "<automation-id>" });' \
  --context local
```

The trigger returns a `run_id`; poll
`client.operations.getRun(Number("<run-id>"))` until it reaches a terminal
status. Keep external actions approval-gated unless the user explicitly approves
them. If the Automation declares persisted output, search for a distinctive value
from that output:

```bash
npx @lobu/cli@latest memory run search_memory \
  '{"query":"<distinctive output>"}' --context local
```

Show the returned event or entity and its returned `view_url`. For a run-result-only
or reaction-only Automation, show the completed run and use the Automation's
`view_url` from `client.automations.list()` instead. Never construct a Lobu URL
from an id.

## Cloud deployment

Local success does not select a cloud target. If the user asks to deploy, list
contexts, explicitly select the intended cloud context, and preview the exact
plan:

```bash
npx @lobu/cli@latest context list
npx @lobu/cli@latest context use "<cloud-name>"
npx @lobu/cli@latest apply --dry-run
```

Show the target organization and plan, then wait for confirmation before the
real `lobu apply`. Repeat the selected Web UI, direct chat, MCP, connector,
Automation, and chat-platform checks against the deployed target.
