M125 — closing 4 vapor gaps

An audit of prior M125 PRs revealed 4 places where specs / dead code / lies shipped instead of working code. This PR finishes each one with verified end-to-end tests.

Gap 1references/boot-sequence.md described fictional portless API
FIXED

Before — fictional

portless start --domain $SUBDOMAIN --tls --lan --background
portless ls --json | jq ...
portless stop --domain $SUBDOMAIN

After — verified portless 0.10.x

portless proxy start (no --domain flag)
portless <name> <cmd> (wraps, not sidecar)
portless list (text, not JSON)
portless get <name> (canonical URL)
Gap 2references/state-schema.md described wrong shape
FIXED
// Before — described 4 keys, actual file has 2-3 (wrapper-fused)
processes: {
  portless?:  { pid, command },
  devServer?: { pid, command },
  emulate?:    { pid, command },
  agentBrowser:{ sessionName }
}
// After — matches what boot.sh actually writes
processes: {
  portlessWrapper: { pid, command },  // owns dev server lifecycle
  agentBrowser:    { sessionName },
  emulate?:        { pid, command }
}
Gap 3posttool/expect/snapshot-recorder was dead code
FIXED
// Hook regex: /ROUTE\|([^\n|]+)/ and /ARIA\|(.+)/
// Reality: /ork:expect emits RUN_COMPLETED|passed but NEVER ROUTE| or ARIA|
//          → hook fired, found neither tag, exited silent on every run

Patches:
1. expect/scripts/report.sh — pass-through ROUTE| and ARIA| tags from stdin
2. expect-agent.md — emit ROUTE|<path> before route's first STEP_START
                     emit ARIA|<capped json> after route's last STEP_DONE

Smoke test (synthetic input):
$ cat input.json | node bin/run-hook.mjs posttool/expect/snapshot-recorder
{"continue":true,"hookSpecificOutput":{"additionalContext":
  "ARIA snapshot recorded: route=/dashboard commit=0ce30edd."}}
$ cat .claude/state/expect-snapshots/dashboard/0ce30edd*.json
{
  "route": "/dashboard",
  "parentCommit": "0ce30eddea2a3e17ae02eb7c93b70b633c72f181",
  "capturedAt": "2026-04-27T20:10:50.368Z",
  "ariaSummary": "{\"role\":\"WebArea\",\"name\":\"Dashboard\"}"
}
Gap 4/ork:emulate-seed --auto was spec-only (no scripts/ dir)
FIXED
New: src/skills/emulate-seed/scripts/auto-discover.sh

3 modes:
  (default)  report mappings on stderr
  --json     emit machine-readable JSON
  --apply    write emulate.config.yaml (refuses overwrite without --force)

Verified end-to-end against synthetic package.json:
  next-auth + stripe + @vercel/blob + @octokit/rest

Output:
Detected:
  @octokit/rest  →  github · Any GitHub API client
  next-auth      →  google-oauth, apple-auth, microsoft-entra
  stripe         →  stripe
  @vercel/blob   →  aws · @vercel/blob is S3-compatible

Union: apple-auth, aws, github, google-oauth, microsoft-entra, stripe

--apply writes valid YAML:
  services:
    apple-auth: {}
    aws: {}
    github: {}
    google-oauth: {}
    microsoft-entra: {}
    stripe: {}

Verification — all green

npm run build                  ✓ 108 skills, 37 agents, 27 commands
bash scripts/stamp-counts.sh --check   ✓ idempotent
npm run test:mdx               ✓ 256/0
bash bin/validate-counts.sh    ✓ 107 / 37 / 185, version 7.73.0

End-to-end smoke tests:
  /ork:dev boot/stop/status    ✓ already verified in #1536
  emulate-seed --auto          ✓ synthetic + real test
  snapshot-recorder hook       ✓ writes per-(route,commit) JSON
  expect protocol              ✓ ROUTE/ARIA tags pass through report.sh