Skip to content

Development

The codebase is Odin plus explicit Python child tools. Run checks from the repository root.

Build and test

odin check . -vet
odin test .
/opt/homebrew/bin/python3 -m unittest discover -s tools -p 'test_*.py' -v
shaders/build/main --if-needed
./tools/run_macos_app.sh --build-only
git diff --check

Run odin test . and the app build serially. Both may use the repository's default output path; overlapping them can replace the test executable with the application binary before the test runner starts.

Normal GUI startup is:

./tools/run_macos_app.sh

main.odin starts the editor directly. It has no alternate CLI dispatch or headless worker mode.

The GUI is the only supported user entry point. Project authoring, Case and Job creation, PHITS execution and monitoring, Result opening, Study assessment, and ML operations must be reachable from RAMAL-EBX. Commands documented below are development, debugging, integrity-verification, or child-process boundaries; they are not alternate user workflows. When a real workflow fails, reproduce and repair it through the GUI before accepting a command-line workaround.

Native macOS accessibility and input

RAMAL's visible ImGui buttons are registered each frame by ui_button and its semantic wrappers. On macOS, macos_accessibility.odin mirrors those live items as retained NSAccessibilityElement children of the SDL content view; it does not create an overlay or a second UI model. Accessibility frames are updated in the content-view coordinate system, and stale elements are pruned when the ImGui item disappears.

The main loop owns a Cocoa autorelease pool for each frame, alongside Odin's temporary allocator reset. SDL's internal pools do not cover the application's native accessibility calls. Without this scope, temporary Cocoa objects can accumulate while the editor is idle.

On 2026-09-09, the long-running Design process had a 7.7 GiB physical footprint and approximately 73 million default-zone allocations (7.3 GiB allocated). After adding the frame pool and reopening the same saved Design, native checks showed about 37,000–50,000 allocations and a 366–375 MiB sampled footprint over a roughly two-minute comparison, ending at 369 MiB. This is a short regression check, not an overnight endurance result. Use vmmap -summary <pid> for footprint and heap counts; RSS alone misses the compressed/swapped memory in this failure.

An Accessibility API press queues the registered ImGui item ID. The matching button wrapper consumes that ID on the next frame, so the existing production callback remains the only action path. Disabled ImGui controls are exposed as disabled and cannot be activated through AX. The SDL/ImGui event bridge also forwards the mouse-button event's own coordinates before backend processing so a native or injected click does not require a preceding mouse-motion event.

Runtime and local files

The active PHITS installation is external at /Users/faiz/phits; do not copy or commit it. Install requirements.txt into the Python environment used to launch the GUI. Research tasks invoke python3 directly, so missing or incompatible dependencies fail in the visible task log. Case evidence calls from Odin use the system Python for the strict runner and remote tools.

Preserve these local paths:

  • projects/ — user Projects and scientific evidence;
  • ramalebx.sublime-project and ramalebx.sublime-workspace — Sublime Text project files;
  • resources/fonts/default.ttf — runtime font;
  • shaders/compiled/ — shader files loaded by the renderer; and
  • shaders/build/bin/ and shaders/build/lib/ — local shader compiler files.

Ignored files are not automatically disposable. Do not use git clean -fdX as a general cleanup command because it can remove Project workspaces and runtime assets. Routine disposable files are .DS_Store, *.dSYM/, and empty temporary directories.

Case runner checks

The strict runner in tools/run_case_attempt.py supports:

python3 tools/run_case_attempt.py --verify-succeeded-attempt <attempt-directory>
python3 tools/run_case_attempt.py --resolve-result-roles <attempt-directory>

Preparation requires the Attempt ID, source input, immutable Case document, content-addressed Case scientific specification, Attempt root, PHITS launcher, multiplier file, all four result roles, and explicit maxcas, maxbch, and rseed controls. The runner validates the nested scientific schema, snapshots both Case records, and inventories and hashes every decisive file.

Remote PHITS checks

tools/remote_phits.py is the GUI child-process transport boundary, not a second user-facing runner. It loads the strict profiles document from ~/Library/Application Support/RAMAL-EBX/remote-profiles.json, stages a prepared Attempt atomically, watches the detached worker, and transfers only a terminal Attempt that passes run_case_attempt.py verification. Keep the profile outside the repository. Optional non-default ssh_port and ssh_host_key_alias values are validated and applied consistently to SSH/SCP. Use a second profile for a temporary forward tunnel; do not overwrite the direct profile or disable host-key checking.

Focused transport coverage is in tools/test_remote_phits.py. It covers profile validation, -envnone ordering, containment, transfer replacement, batch progress, cancellation/recovery state, and manifest compatibility. Do not use the transport commands as an end-user shell workflow or launch a long cluster run as a test; exercise the Simulate GUI and inspect only filtered bat[...] progress there. Verbose SSH/MPI/PHITS output belongs in Diagnostics.

Research tools

/opt/homebrew/bin/python3 -m pip install -r requirements.txt
python3 tools/build_dataset.py --project <project.ramal-project> --spec <dataset-spec.json>
python3 tools/model_pipeline.py train --dataset <dataset.ramal-dataset> --model-id <id> --display-name <name>
python3 tools/model_pipeline.py evaluate-final --model <model.ramal-model>
python3 tools/model_pipeline.py predict --model <model.ramal-model> --spec <prediction-spec.json>
python3 tools/model_pipeline.py verify-prediction --prediction <prediction.ramal-prediction> --result <result.ramal-result>

The GUI starts these as visible asynchronous ML_Task processes. Study execution stays in Odin orchestration and reuses the sole Case runner.

Generated codebase tutorial

tools/generate_codebase_tutorial.sh runs the pinned PocketFlow Codebase Knowledge pipeline against the local source. Its only provider change is the LLM boundary: each PocketFlow prompt is passed to codex exec, which reuses the developer's saved ChatGPT sign-in. No API key is required.

View the current tutorial locally without making model calls:

./tools/view_knowledge_base.sh

The site opens at http://127.0.0.1:8001/. Set RAMAL_DOCS_PORT to use a different local port.

After meaningful code changes, regenerate through PocketFlow and then serve the validated site:

./tools/view_knowledge_base.sh --update-software

The generated Markdown is written to docs/gen_ai/software/codebase-tutorial/. PocketFlow's prompt cache is retained in its ignored local checkout, so unchanged work can be reused on later updates.

Regenerate only the Paper 1 research dashboard after its source records change:

./tools/view_knowledge_base.sh --update-paper1

Source boundaries

  • HLSL source is under shaders/src/; compiled shader output is under shaders/compiled/.
  • shader_dev.odin owns development freshness checks; renderer code loads compiled outputs.
  • storage.odin and project_storage.odin own write/path/hash primitives.
  • Scene_State is an in-memory shared shape for an editable Design and a reconstructed immutable Result; it is not a new persisted scene format.
  • Hard changes are applied to the current source and current files. There is no compatibility reader or second execution path.