# QA

Validate the installed candidate as a human would use it. Use disposable
profiles and an unfunded fixture; preserve existing product source and active
processes.

## Candidate and provenance

```bash
export CANDIDATE=/path/to/mm-harness-candidate.tgz
export QA_HOME="$(mktemp -d "$HOME/mmh-qa.XXXXXX")"
export QA_PREFIX="$QA_HOME/npm"
HOME="$QA_HOME" npm install -g --prefix "$QA_PREFIX" "$CANDIDATE"
export PATH="$QA_PREFIX/bin:$PATH"
mm-harness --version
```

- [ ] The executable and dependencies resolve inside the isolated prefix.
- [ ] No dependency is a symlink or resolves through a local Farmslot checkout.
- [ ] Record the tarball SHA-256 and product SHAs.
- [ ] Product trees start and finish without tracked changes.

## Common

Run inside each Extension, Mobile, and Core checkout:

```bash
mm-harness doctor
mm-harness doctor --json
mm-harness status
mm-harness actions
mm-harness run --list
mm-harness run runner.smoke --describe
mm-harness run runner.smoke --plan
mm-harness run runner.smoke
mm-harness last --json
```

- [ ] Product, checkout, slot, ports, and next action are correct.
- [ ] Human output is concise and evidence paths are absolute.
- [ ] JSON output is one parseable document without color or prose on stdout.
- [ ] `run` chooses a checkout-local artifact directory; an explicit
  `--artifacts-dir` still wins.
- [ ] Reports, trace, diagnostics, executed recipe, and manifest exist and agree.
- [ ] `last --json` reconstructs the run without re-executing it.

Recovery checks:

```bash
mm-harness actions --wat
mm-harness run missing.recipe --describe
mm-harness doctor --fix
mm-harness verify
```

- [ ] Bad input fails before runtime work with a stable code and one exact next
  action.
- [ ] `doctor --fix` is idempotent and does not choose a fixture or launch.
- [ ] With `capture-helper` absent, Extension reports CDP screenshots and Mobile
  reports `simctl`/ADB screenshots; video is honestly unavailable.

Run the bounded multi-platform preflight when all three checkouts are available:

```bash
yarn qa:human \
  --extension /path/to/metamask-extension \
  --mobile /path/to/metamask-mobile \
  --core /path/to/metamask-core \
  --artifacts-dir temp/human-qa
```

It supplements the visible checks below; it does not replace them.

## Extension

Fresh MetaMask Extension needs its normal product configuration and
checkout-pinned Chromium. Follow the product files; do not invent values:

```bash
cd /path/to/metamask-extension
cp .metamaskrc.dist .metamaskrc
${EDITOR:-vi} .metamaskrc
yarn playwright install chromium
mm-harness launch --verify
mm-harness fixtures set
mm-harness run wallet.smoke
mm-harness logs --source extension
mm-harness logs --source dapp
mm-harness logs --source webpack
mm-harness debug
```

- [ ] Missing/placeholder Infura configuration returns
  `EXTENSION_PRODUCT_CONFIG_REQUIRED` before build or browser startup.
- [ ] Missing Chromium returns `EXTENSION_BROWSER_REQUIRED` without using system
  Chrome.
- [ ] Launch uses the checkout-owned profile, opens one MetaMask surface, avoids
  keychain prompts, and preserves keyboard focus by default.
- [ ] A second launch reuses the watcher/profile without duplicate tabs.
- [ ] Two source edits rebuild incrementally; refresh shows each change; revert
  restores a clean tree.
- [ ] Log sources are distinct.
- [ ] `debug` opens connected DevTools for the active Extension surface;
  `location.href` returns its `chrome-extension://` URL and remains connected.

## Mobile

```bash
cd /path/to/metamask-mobile
mm-harness provision runway ios
mm-harness launch ios --verify
mm-harness fixtures set
mm-harness call metamask.wallet.ensure_unlocked
mm-harness run wallet.smoke
mm-harness logs --source app
mm-harness logs --source metro
mm-harness debug
```

- [ ] Simulator opens only when absent and does not steal focus by default.
- [ ] A second launch reuses the running simulator and Metro.
- [ ] Fixture setup and unlock show the intended redacted account without
  mnemonic/private-key output.
- [ ] Status matches verified product routes: `Login`/`LockScreen` are locked;
  `WalletView` is unlocked.
- [ ] App and Metro logs are separate.
- [ ] A restarted Metro rotates the previous `metro.log`, records its generation and retention actions in launch JSON, and classifies bundle failures only from the current log.
- [ ] `mm-harness logs --full` preserves errors, completion, and meaningful timestamped bundle progress without repeated same-percentage module counts.
- [ ] A JS edit rebuilds through Metro and appears after reload without a native
  rebuild; revert restores a clean tree.

When Android/ADB is available, repeat with:

```bash
mm-harness launch android --device <serial> --verify
```

## Core

```bash
cd /path/to/metamask-core
mm-harness doctor
mm-harness call metamask.wallet.list_accounts scope=selected
mm-harness run runner.smoke
mm-harness logs
mm-harness debug
```

- [ ] Doctor reports a headless controller surface and no capture requirement.
- [ ] Account output is fixture-backed and redacted.
- [ ] Smoke writes the complete evidence package without launching an app.
- [ ] Logs/debug fail with truthful headless teaching errors.

## Trust and evidence

- [ ] An untrusted restricted plan fails with `RECIPE_TRUST_REQUIRED` and no
  side effect.
- [ ] A wrong/stale digest fails with `RECIPE_APPROVAL_MISMATCH`.
- [ ] Only the unchanged, reviewed plan executes with its exact approval digest.
- [ ] Human output, JSON, reports, traces, diagnostics, and screenshots contain
  no mnemonic, private key, seed, bearer token, or API credential.
- [ ] Diagnostics contain only events observed in the proof window.
- [ ] Screenshot provenance identifies capture-helper, CDP, simctl, or ADB
  accurately.

## Automated and release gates

```bash
yarn check
bash tests/contract/run.sh
```

Before release:

- [ ] Focused unit tests and full contract suite pass.
- [ ] Packed isolated installation passes the critical Extension, Mobile, and
  Core scenarios.
- [ ] Independent review approves the exact final diff.
- [ ] Known limits are explicit: Extension requires product Infura setup;
  Mobile requires its normal dev-client/device setup; video requires optional
  `capture-helper`; the harness never invents funded fixtures.
- [ ] Existing Farmslot slots remain compatible.

When a slot manager is available, repeat `runner.smoke` in one existing managed
checkout per product and verify its profile/device, ports, processes, and fixture
remain isolated.
