The port is only recognisable if a Monty developer can find any file they know. One rule does that.
The rule
Monty.<CamelCase dirs>.<CamelCase file>.<Class>with two collapses:
- an immediately repeated segment collapses (
frameworks/actions/actions.py→Monty.Frameworks.Actions, not...Actions.Actions); - the class is dropped when it repeats the file name
(
cmp.py::Message→Monty.Cmp.Message,hypotheses.py::Hypotheses→Monty.Frameworks.Models.EvidenceMatching.Hypotheses).
| Python | Elixir |
|---|---|
cmp.py::Message | Monty.Cmp.Message |
geometry.py::SurfacePoseVectors | Monty.Geometry.SurfacePoseVectors |
frameworks/models/buffer.py::FeatureAtLocationBuffer | Monty.Frameworks.Models.Buffer.FeatureAtLocationBuffer |
frameworks/models/abstract_monty_classes.py::Monty | Monty.Frameworks.Models.AbstractMontyClasses.Monty |
frameworks/models/evidence_matching/learning_module.py::EvidenceGraphLM | Monty.Frameworks.Models.EvidenceMatching.LearningModule.EvidenceGraphLM |
frameworks/models/motor_policies.py::SurfacePolicy | Monty.Frameworks.Models.MotorPolicies.SurfacePolicy |
frameworks/experiments/monty_experiment.py::MontyExperiment | Monty.Frameworks.Experiments.MontyExperiment |
frameworks/actions/actions.py::MoveForward | Monty.Frameworks.Actions.MoveForward |
sensor_modules/sensor_module.py::SensorModule | Monty.SensorModules.SensorModule |
simulators/mujoco/simulator.py::MuJoCoSimulator | Monty.Simulators.MuJoCo.Simulator.MuJoCoSimulator |
The actor layer is the one addition: Monty.Runtime.* has no Python
counterpart, because in Python the loop itself is the runtime.
The second package: tbp.teleop
Teleop is the real-time GUI and teleoperation tool for Monty (matplotlib panels, buttons, sliders, a live plotter). The same recognisability rule applies with its own namespace:
| Python | Elixir |
|---|---|
src/tbp/teleop/controls.py::Controls | Teleop.Controls.Controls |
src/tbp/teleop/panels.py::Panel | Teleop.Panels.Panel |
src/tbp/teleop/plotter.py::Plotter | Teleop.Plotter.Plotter |
src/tbp/teleop/live_plotter.py::LivePlotter | Teleop.LivePlotter.LivePlotter |
src/tbp/teleop/policies.py::... | Teleop.Policies.... |
src/tbp/teleop/helpers.py::... | Teleop.Helpers.... |
src/tbp/teleop/default.py::... | Teleop.Default.... |
tbp.teleop is MIT-licensed like Monty; the point of the namespace is that a
teleop developer can find their module here without a translation table.
How each part is meant to land in a browser is a separate decision, made in
architecture.md: the matplotlib figure becomes LiveView
components, a StepHook stays a hook, and the mouse/keyboard controls become
LiveView events. The module map records where the logic lives, not how it is
drawn.
The map
lib/monty/module_map/data.ex is generated
from the checkouts:
mix monty.module_map.gen # writes the module (both packages)
mix monty.module_map.verify # fails on drift
It is written as Elixir rather than as a file read at run time. What the map says decides which modules this application claims to implement, and every port question starts there, so it belongs beside the code it describes — not at the end of a path handed to a reader.
Each entry carries the Python path, the Elixir module, a status
(implemented, partial, planned, excluded) and, for exclusions and partial
ports, a reason. The verifier checks three things, for both packages:
- every Python file in a checkout has an entry;
- every entry marked
implementedorpartialpoints at a module that exists; - every entry marked
excludedorpartialsays why.
With no checkout it checks the last two only, and says which packages it could not check from source rather than pretending it did: the map names the commit it was generated from, and nothing a build or a test does needs the checkout. A checkout that has moved since is reported too — the map still describes the commits it names, which is a fact to read, not a failure.
The current counts are what mix monty.module_map.verify prints. They live
there and in data.ex, never here: a number
copied into prose is wrong by the next commit.
The generated file's counts are the honest progress bar for the port: the UI will show per-experiment how much of the config it needs is already implemented.
Claiming a module
- Pick an entry from
lib/monty/module_map/data.ex. - Create the module at its mapped name.
- Port the behaviour as pure functions, keeping Monty's vocabulary.
- Test it — against a Monty fixture when numbers are involved.
mix monty.module_map.gen && mix monty.module_map.verify.scripts/quality.sh.
Marking something excluded is allowed; leaving it unexplained is not. A
verdict of excluded is a claim about somebody else's code, so
planned-classes.md keeps the evidence for each one and
says which classes are still owed.
A module that is here but only as far as anything here uses it is partial, and
it makes a claim about our code that has to be checked the same way:
partial-classes.md argues each one from the module's own
admission of what it leaves out, and says how the list was swept for.