Skip to content

Pack doctor

Some Pack mistakes don’t throw an error anywhere. A stale hash baked into your adapter, an overlay you forgot to rebuild, a crowd scenario that quietly targets an event you renamed last week — the bridge just… doesn’t do the thing you expected, and you’re left guessing why. mobrule dev doctor checks for all of these in one pass.

Terminal window
mobrule dev doctor

Run it from your Pack directory (the one with pack.toml in it), or pass a path:

Terminal window
mobrule dev doctor path/to/my-pack

Every check is independent, and most work with no bridge running at all — just your Pack directory on disk:

  • Does pack.toml load? Uses the exact same loader the bridge does, so if this passes, the bridge will load your pack too. If it fails, you get the real parse/validation error, not a guess.
  • What’s the manifest hash? The same sha256:... value mobrule pack print-hash gives you, printed for the checks below to compare against.
  • Any stale hash pins? Scans your Pack tree for sha256:... literals (the kind an adapter bakes in at build time to detect manifest drift) and flags any that don’t match the current hash. This is the single most useful check here — a stale pin causes the adapter to reject the bridge’s handshake in a loop, with no obvious error message anywhere.
  • Is the overlay built? If you declare [overlay], checks that overlay/dist exists and isn’t empty, and warns if your overlay/src has newer files than overlay/dist (you edited and forgot to rebuild).
  • Do your datasets parse? Every file a [data.<name>] entry points at gets parsed as JSON.
  • Does your crowd scenario make sense? If you ship a crowd.toml, checks that every event named in [weights] or [corpus] is one your manifest actually declares. A typo here doesn’t error, it just silently never fires.

If a local bridge happens to be running, three more checks kick in:

  • Is this Pack the active one? Just informational, not a warning either way.
  • Does the hash match what’s running? If this Pack is active and you’ve edited pack.toml since, you’ll see a mismatch — a nudge to swap/reload.
  • Are your launcher paths configured? If your Pack declares [[adapter.path]] entries (a ROM, an emulator binary, that kind of thing), checks whether they’re set in this machine’s Launcher panel.

No bridge running? Those three just show up as skipped — everything else still runs.

ok manifest_load: tv.mobrule.mypack v0.3.0 loaded OK (7 events)
ok manifest_hash: sha256:a7d90de1be35210a094d45efb4f9a28afb96c97d95a117d0ad62dc228997530c
WARN stale_hash_pins: adapter.py:42 (found sha256:aaaa..., expected sha256:a7d9...)
hint: baked hash pin doesn't match this pack.toml — rebake and rebuild the adapter
ok overlay_dist: dist present at /path/to/mypack/overlay/dist
skip datasets: no file-backed datasets declared
ok crowd_scenario: weights/corpus reference declared events
skip bridge_active_pack: skipped (bridge unreachable)
skip bridge_hash_parity: skipped (bridge unreachable)
skip adapter_paths: skipped (bridge unreachable)

ok and skip are both fine — skip just means a check’s precondition wasn’t met (no bridge, no overlay declared, whatever). WARN is worth a look but doesn’t fail the command. FAIL does: the exit code is 1 if anything fails, 0 otherwise, so it’s safe to drop into CI.

Add --json for a machine-readable array of the same rows:

Terminal window
mobrule dev doctor --json