Imported from IgorGanapolsky/mac-yolo-safeguards (
hermes-mobile/AGENTS.md). Install upstream withnpx skills add IgorGanapolsky/mac-yolo-safeguards --skill hermes-mobile. Copyright stays with the author.
AGENTS.md — Hermes Mobile
Canonical repo rules: ../AGENTS.md. This file adds mobile-only obligations so agents do not wait for the user to ask.
Standing orders (no reminders)
- Before any edit — run
../../bin/agent-loop --health(validates hooks, MCP, skills, E2E, plan claims). Full cycle:../../bin/agent-loop(Recollect→Plan→Observe→Act→Evaluate→Learn). - Session start — parent repo runs
node tools/agent-session-start.js(pairing, LaunchAgent health, continuous E2E status). Do not skip when touching this tree. - After any edit under
src/,app.json, or.maestro/— in the same turn before claiming fixed/shipped:npm test -- --no-coverage --watchman=false- Kick autonomous E2E:
launchctl kickstart -k "gui/$(id -u)/com.igor.hermes-mobile-continuous-e2e"ornpm run e2e:continuous:once
- Never ask the user to run Maestro, reload Metro, plug in a phone, or tap Send — use
adb,hermes-mobile-pair.js, and scripts. - Read
docs/proofs/continuous/latest.jsonbefore saying chat/E2E is healthy. Ife2e≠pass, say so with the JSON — do not claim device UX is verified. - Phone connected (
adb devices) → E2E prefers Android automatically viascripts/run-e2e.sh. - Phone install only via release path —
npm run android:phoneorscripts/install-phone-release.sh; neverexpo run:androidon device (npm run androidblocks when adb sees a phone). - RN performance work — read
.cursor/skills/react-native-best-practices/SKILL.mdfirst (Callstack 2026 optimization guide skills). Install/refresh:bash ../scripts/install-callstack-agent-skills.sh. Measure before optimizing. - Real users product — Hermes Mobile ships to real users, not Igor-only dogfood. No feature is "done" if it requires
adb, dev backdoor, or pre-paired Igor Mac. - Brand-new user testing (permanent) — always treat every test as if it is a brand new user: fresh install, no saved profiles, no
developerLeashUnlock, cellular or Wi‑Fi only, release APK. Maestro and manual proofs must reflect that mindset. - Multi-Mac API keys — Mac mini and MacBook Pro can have different
API_SERVER_KEYvalues. Pair mini vianode tools/hermes-mobile-pair.js --mini-tailscale(SSH-fetches mini key); never paste the laptop.envkey when targeting another machine. - Device/Maestro chat input (permanent) — When testing via Maestro,
adb input text,agent-device, or any device/E2E automation that types into the chat composer, use onlymake money today. Never type gibberish probe strings (typeableProbeB,e2e-chat-send-persist,smoke test message, etc.). Session titles/IDs in URLs are exempt. Enforced bypreventRecurrenceContract.test.ts. - Versioning / OTA / store — JS fixes ship via EAS Update (
productionchannel, CImobile-ota.yml). New store binaries only for native changes or marketingexpo.versionbumps. Canonical rules: docs/VERSIONING-AND-RELEASES.md. Do not claim “every fix needs the store” or invent semver automation that does not exist. - No production OTA without fresh-user gate (permanent, crisis 2026-07-15) — Never run
eas update --channel production/npm run ota:publishunlessdocs/proofs/continuous/latest.jsonhase2e=passornpm run e2e:fresh-user(.maestro/stranger-cold-start.yaml) wrote a pass proof. Gate:npm run ota:gate→scripts/require-fresh-user-ota-gate.sh. CI must not auto-publish production on everymainmerge.e2e=skippedis not pass. - agent-device (Callstack) — For connection-crisis / Tailscale / fresh-user UI proofs, use
agent-device(orbash scripts/agent-device-connection-proof.sh). Install/refresh:bash ../scripts/install-agent-device.sh. Matrix vs Maestro vs adb: docs/AGENT-DEVICE.md. Maestrolatest.jsonremains the ship gate; agent-device alone is note2e=pass. Do not claim Connected when UI shows Reconnecting. - No desktop hijack — Never drive Igor's interactive Google Chrome, steal macOS focus, or use Computer Use unless he explicitly asked in that message. Parent rule: ../AGENTS.md § No desktop hijack. Prefer
gh, Play/ASC APIs, Stripe CLI,adb, SSH. Chrome CDP LaunchAgents stay gated off (HERMES_ALLOW_INTERACTIVE_CHROMEdefault 0).
Autonomous infrastructure (already installed on Igor's Mac)
| Piece | Interval | Check |
|---|---|---|
LaunchAgent com.igor.hermes-mobile-continuous-e2e |
15 min | npm run e2e:continuous:status |
GitHub mobile-continuous.yml |
6 h | unit + coverage on push schedule |
Install/repair: bash ../scripts/install-agent-launchagents.sh (agent runs this if missing — not the user).
Verification ladder
| Layer | Command |
|---|---|
| Unit | npm test / npm run test:ci |
| Contract | npm run test:release-safety |
| Connection UI proof | bash scripts/agent-device-connection-proof.sh (exploratory; see AGENT-DEVICE.md) |
| E2E (local) | npm run e2e:continuous:once |
| E2E (fresh-user / OTA gate) | npm run e2e:fresh-user then npm run ota:gate |
| E2E (device release) | npm run e2e:device |
| Accelerated Maestro | npm run e2e:accelerated (agent-device test --maestro) |
Details: docs/TESTING.md.
Fresh-user onboarding contract (permanent)
North star: Every launch is a stranger who knows nothing. One primary CTA per connection state. Silent auto-heal ~30s before numbered human steps.
| State | User sees | Must NOT see |
|---|---|---|
| First launch, no saved Mac | ConnectMacGate + numbered steps + Find computers |
"Pair relay", "gateway", "LAN", competing banners |
| Disconnected, saved Mac | Silent heal in CodexCommandCenter; after ~30s ChatConnectionPanel + steps |
"Connected" + "Can't reach" at once |
| Choose Mac modal | Tailscale Add [name] at top when tailnet probe succeeds | Mac mini buried only in Settings |
| Cellular, no Tailscale | Step 4 + Use Tailscale from cellular title | Home Wi‑Fi IP instructions without context |
Infer onboarding complete from valid saved gatewayProfiles (no separate flag required).
Unit tests (required on onboarding copy changes):
src/__tests__/freshUserOnboarding.test.ts— step copy, heal timing, jargon-freesrc/__tests__/FreshUserOnboardingCard.test.tsx— numbered steps rendersrc/__tests__/ChatConnectionPanel.test.tsx— fresh-user card, single CTA, Tailscale chip
Maestro: connect-mac-gate must show connect-mac-onboarding-card on cold start without demo deep link (future flow); demo bootstrap uses hermes://setup?demo=1 and hides the gate.
Copy rules: Say Your Mac, Home Wi‑Fi, Find computers — never "gateway", "LAN", or "Pair relay" in first-run / disconnected primary UI.
Greptile AI PR review
Version-controlled rules: ../.greptile/ + .greptile/. Agent guide: docs/GREPTILE-CODE-REVIEW.md.
On PRs that touch connect, onboarding, pairing, Tailscale, auth probes, OTA, or multi-Mac keys: read Greptile findings before claiming fixed/shipped. Force review with @greptileai review once the GitHub App is installed. Do not treat green CI alone as connect/onboarding proof when Greptile flags a fresh-user or wrong-key regression class.
Prevent recurrence (July 2026)
Playbook: docs/PREVENT-RECURRENCE-JULY-2026.md. Session gates: vault pull + plan.md §2 before parallel work; bash scripts/agent-adb-refresh.sh before phone/pair; bash scripts/agent-pre-asc-edit.sh before ASC review notes; read docs/proofs/continuous/latest.json before device/chat ship claims (e2e=skipped is not pass). Cursor: single-pass — no duplicate subagents on the same file domain or PR.