Clean-machine UAT checklist (G18)
Commands-only runbook for installing from a GitHub Release binary (no repo checkout as the runtime install source).
Do not cut a non-alpha stable tag from this checklist alone. Product remains alpha until G1 + G18 + remaining GA vetoes pass.
Isolation honesty (same physical Mac)#
Default production identities stay:
- LaunchAgent
dev.herdr-mcp.server - loopback port
8772 - config root
~/.config/herdr-mcp - user CLI
~/.local/bin/herdr-mcp
| Attempt | Safe on dogfood Mac? | Why |
|---|---|---|
TMPHOME / HERDR_MCP_CONFIG_DIR only |
Partial probes only | Paths isolate, but default label/port still collide; status/doctor can report dogfood :8772 |
Same-user default herdr-mcp install |
No | Mutates dogfood LaunchAgents / ~/.local/bin/herdr-mcp |
Same-user named instance (--instance uat / HERDR_MCP_INSTANCE=uat) |
Yes for local runtime UAT | Distinct label dev.herdr-mcp.uat.server, non-8772 port, ~/.config/herdr-mcp-uat; never rewrites default user CLI |
Second Mac or VM (free :8772, empty default dev.herdr-mcp.*) |
Yes | Full default-instance G18 including native-host / public ChatGPT path |
Named-instance evidence advances G18 local install/doctor/status on the dogfood Mac. It does not replace a second-Mac default-instance seal for native-host + public OAuth when those must share production identities.
Requires a Release that includes instance isolation (first: v0.4.0-alpha.16 or newer). Do not claim named-instance UAT from v0.4.0-alpha.15.
Platform under test#
First-GA recommendation: macOS Apple Silicon only.
- Windows Release binary: preview / optional observation, not first-GA lifecycle seal.
- Linux lifecycle: not claimed.
Preconditions#
- Herdr installed per https://herdr.dev.
- No prior
herdr-mcpcheckout required for the runtime path. - Network access to GitHub Releases and (for ChatGPT path) Cloudflare.
- For default-instance install: confirm
launchctl list | awk '$3 ~ /herdr-mcp/'is empty and nothing listens on:8772. - For named-instance install on a dogfood Mac: leave default
dev.herdr-mcp.server/:8772alone; do not run Link cutover /native-host installagainst dogfood Chrome from the UAT binary.
Second Mac needs an independent Edge Worker#
Public ChatGPT MCP on a second Mac is not "reuse dogfood URL + Link secret." Edge is single-tenant per Worker:
DEFAULT_WORKSTATION_IDrouting: Each deployed Worker binds public/mcp(and OAuth discovery) to oneDEFAULT_WORKSTATION_ID. Requests without an explicit workstation header/query resolve to that ID. One Worker → one logical workstation for the public path.- One active Link per
workstation_id: Link connects to/ws/{workstation_id}. The Edge Durable Object accepts exactly one active Link socket per ID; a newerhellomarks the previous Link inactive and closes it (superseded by newer workstation link). - Do not reuse dogfood identities on pi: Pointing the UAT Mac at
herdr-edge-prod+prod-real-runtime(or any live dogfood Worker /DEFAULT_WORKSTATION_ID) would either kick dogfood's production Link or route ChatGPT tool calls to the wrong machine. Forbidden for G18 seal.
Deploy a machine-specific Worker before section B: unique Worker name, unique DEFAULT_WORKSTATION_ID (e.g. pi-uat-<date>), OAUTH_ISSUER matching that Worker URL, and set the same workstation_id on Link (HERDR_WORKSTATION_ID). Follow Agent-assisted installation §6 (Edge deploy + LINK_SHARED_SECRET); keep workers_dev = true and routes = [] for UAT.
Internal GA UAT only (not end-user install): copy the Second Mac GA UAT Agent prompt to the pi coding Agent (agent-first contract; Cloudflare Token pause, Link env override, final report template). Regular users install via install.md or agent-install.md.
One-command operator bootstrap (second Mac, default instance)#
Replace TAG if a newer prerelease is under test:
TAG=v0.4.0-alpha.16
REPO=whshang/herdr-mcp
WORKDIR="${HOME}/herdr-mcp-clean-uat"
mkdir -p "$WORKDIR/bin" "$WORKDIR/dl" && cd "$WORKDIR"
gh release download "$TAG" -R "$REPO" -D dl \
-p "herdr-mcp-*-aarch64-apple-darwin" \
-p "release-manifest.json" \
-p "herdr-mcp-extension-*.zip" \
-p "herdr-mcp-extension-*.zip.sha256"
install -m 755 dl/herdr-mcp-*-aarch64-apple-darwin bin/herdr-mcp
export PATH="$WORKDIR/bin:$PATH"
herdr --version
herdr api schema >/dev/null
herdr-mcp --version
herdr-mcp install
herdr-mcp doctor
herdr-mcp status
herdr-mcp update check
# Extension (optional for G15 residual on the clean machine):
shasum -a 256 -c dl/herdr-mcp-extension-*.zip.sha256
mkdir -p ~/.config/herdr-mcp/extension
unzip -o dl/herdr-mcp-extension-*.zip -d ~/.config/herdr-mcp/extension
# Chrome: Load unpacked -> ~/.config/herdr-mcp/extension
herdr-mcp native-host install
herdr-mcp native-host status
No git clone. No npm ci for the runtime path.
Same-Mac named instance (when a second Mac is unavailable)#
Use a downloaded Release binary only (never target/*/herdr-mcp). Keep dogfood on the default instance.
TAG=v0.4.0-alpha.16
REPO=whshang/herdr-mcp
WORKDIR="${HOME}/herdr-mcp-clean-uat"
mkdir -p "$WORKDIR/bin" "$WORKDIR/dl" && cd "$WORKDIR"
gh release download "$TAG" -R "$REPO" -D dl \
-p "herdr-mcp-*-aarch64-apple-darwin" \
-p "release-manifest.json"
install -m 755 dl/herdr-mcp-*-aarch64-apple-darwin bin/herdr-mcp
export PATH="$WORKDIR/bin:$PATH"
export HERDR_MCP_INSTANCE=uat
# Preflight: dogfood must stay untouched
readlink "$HOME/.config/herdr-mcp/runtime/current"
launchctl list | awk -v label='dev.herdr-mcp.server' '$3 == label { print $1, $2, $3 }'
herdr-mcp --version
herdr-mcp --instance uat install
herdr-mcp --instance uat doctor
herdr-mcp --instance uat status
herdr-mcp --instance uat update check
herdr-mcp --instance uat service status
# Expect isolated identities
test -x "$HOME/.config/herdr-mcp-uat/runtime/current/herdr-mcp"
launchctl list | awk -v label='dev.herdr-mcp.uat.server' '$3 == label { print $1, $2, $3 }'
# Dogfood still default:
readlink "$HOME/.config/herdr-mcp/runtime/current"
ls -l "$HOME/.local/bin/herdr-mcp"
launchctl list | awk -v label='dev.herdr-mcp.server' '$3 == label { print $1, $2, $3 }'
Named-instance extension (same Mac, static only)#
Extract the Release extension zip into the uat config root (not dogfood ~/.config/herdr-mcp/extension):
export HERDR_MCP_INSTANCE=uat
gh release download "$TAG" -R "$REPO" -D "$WORKDIR/dl" \
-p "herdr-mcp-extension-*.zip" \
-p "herdr-mcp-extension-*.zip.sha256"
shasum -a 256 -c "$WORKDIR/dl"/herdr-mcp-extension-*.zip.sha256
mkdir -p "$HOME/.config/herdr-mcp-uat/extension"
unzip -o "$WORKDIR/dl"/herdr-mcp-extension-*.zip -d "$HOME/.config/herdr-mcp-uat/extension"
herdr-mcp --instance uat doctor
# expect: local-ipc PASS; native-messaging absent (Chrome host name dev.herdr.mcp is singleton)
Static smoke (no Chrome required; run from a checkout):
node tests/manual/extension_smoke.mjs
node tests/manual/background_bind_test.mjs
node --test tests/queued-insert.test.mjs
Do not run herdr-mcp --instance uat native-host install on the dogfood Mac: it would overwrite the production Chrome manifest at NativeMessagingHosts/dev.herdr.mcp.json. Full G15 native-host + Load unpacked seal requires a second Mac default instance or an owner maintenance window on dogfood default instance.
Cleanup when finished (does not touch dogfood):
export HERDR_MCP_INSTANCE=uat
herdr-mcp --instance uat uninstall
Named-instance non-goals on the dogfood Mac#
- Do not run
native-host install/ Chrome Load unpacked against dogfood profiles from this path. - Do not run
link install/link cutover/ seal mutations for the UAT instance on the dogfood Mac. - Public ChatGPT OAuth remains an owner step on a machine/Edge identity you intend to expose; stop at OAuth and record the exact blocked step.
A. Local runtime only#
herdr --version
herdr api schema >/dev/null
# Download the platform binary from GitHub Releases into PATH, then:
chmod +x "$(command -v herdr-mcp)"
herdr-mcp install # default instance on a clean Mac
# or: herdr-mcp --instance uat install # same Mac beside dogfood
herdr-mcp doctor
herdr-mcp status
herdr-mcp update check
Expect:
doctorPASS on local Herdr / runtime / service layers for that instance- default instance: PATH
herdr-mcpmay resolve through~/.config/herdr-mcp/runtime/current - named instance: use
--instance/HERDR_MCP_INSTANCEor the isolatedruntime/currentbinary;~/.local/bin/herdr-mcpstays dogfood - no requirement to
git cloneornpm cifor the local runtime - named-instance
doctormust report the UAT label/port/config root, not dogfood:8772
B. Public ChatGPT path (owner action)#
Follow Installation / Agent-assisted installation using Release binary + temporary Edge bootstrap only, then ChatGPT Connector.
Prefer a second Mac / default instance for this section. Named-instance same-Mac UAT stops before mutating dogfood Link/Edge.
herdr-mcp doctor
# After Edge + Link are configured on THIS clean machine:
# expect Edge configured + edge-reachable + oauth-metadata + mcp-endpoint (401 auth=not-sent)
# without printing tokens
Then the human operator (not an unattended agent) in a new ChatGPT conversation:
- Settings → Connectors → add custom MCP App / Connector with the public Edge URL from install docs
- Complete OAuth in the browser (never paste
HERDR_MCP_TOKENinto ChatGPT) - Confirm OAuth success, then start a new chat so
tools/listis fresh - Verify epoch 2 / 18 tools
- One read-only tool call (
herdr_inspector equivalent) - One real bounded mutation the operator chooses
- One long-task / streaming basics smoke if in scope for this UAT pass
If the operator cannot complete OAuth in this session, leave G7/G18 public path as open and record the exact step blocked (connector add / authorize / tools/list / tool call).
C. Update / rollback (same clean machine / same instance)#
herdr-mcp update check
herdr-mcp update apply
herdr-mcp update status
herdr-mcp doctor
# Controlled rollback only when a previous managed generation exists:
herdr-mcp rollback
herdr-mcp doctor
herdr-mcp status
For named instance, keep HERDR_MCP_INSTANCE=uat (or --instance uat) on every command.
D. Explicit non-goals for this runbook#
- Do not implement Browser Control Plane / true-steer work here (G16 post-GA boundary).
- Do not treat unpacked
extension/from a git checkout as the sealed G15 path. - Do not use
target/*/herdr-mcpor a repo-linked~/.local/bin/herdr-mcpas production evidence. - Do not mutate production Link on the dogfood Mac from the named-instance path.
Evidence to record#
Capture (non-secret) outputs of:
herdr-mcp --version
# default:
readlink "$HOME/.config/herdr-mcp/runtime/current" || true
launchctl list | awk -v label='dev.herdr-mcp.server' '$3 == label { print $1, $2, $3 }'
# named instance:
readlink "$HOME/.config/herdr-mcp-uat/runtime/current" || true
launchctl list | awk -v label='dev.herdr-mcp.uat.server' '$3 == label { print $1, $2, $3 }'
herdr-mcp --instance uat status
herdr-mcp --instance uat doctor
herdr-mcp --instance uat update check
ls -l "$HOME/.local/bin/herdr-mcp"
Attach those to the GA scorecard G18 row. Score named-instance same-Mac evidence as progress toward G18 local runtime, not as a full public-path PASS.