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.
mobrule dev doctorRun it from your Pack directory (the one with pack.toml in it), or pass a
path:
mobrule dev doctor path/to/my-packWhat it checks
Section titled “What it checks”Every check is independent, and most work with no bridge running at all — just your Pack directory on disk:
- Does
pack.tomlload? 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:...valuemobrule pack print-hashgives 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 thatoverlay/distexists and isn’t empty, and warns if youroverlay/srchas newer files thanoverlay/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.tomlsince, 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.
Reading the output
Section titled “Reading the output”ok manifest_load: tv.mobrule.mypack v0.3.0 loaded OK (7 events)ok manifest_hash: sha256:a7d90de1be35210a094d45efb4f9a28afb96c97d95a117d0ad62dc228997530cWARN 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 adapterok overlay_dist: dist present at /path/to/mypack/overlay/distskip datasets: no file-backed datasets declaredok crowd_scenario: weights/corpus reference declared eventsskip 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:
mobrule dev doctor --jsonSee also
Section titled “See also”- Crowd Simulator: the
crowd.tomlthis checks against. - Overlays: what
overlay/distis and how it gets built. - Option datasets: the
[data.<name>]files this validates.