otko/CONTRIBUTING.md
smill f361fee969 feat: named case-result load combinations with full GUI support
Snapshots the current development tree, headlined by proper load
combinations (user request): a reusable LoadCombination entity of
weighted completed static-case results (e.g. 1.2xDead + 1.6xLive).

- core: LoadCombination/LoadCombinationItem entities, Project
  integration (lookup, unique ids, reference validation)
- services: combinations.py (linear superposition + envelope),
  exported via services __init__
- commands: undoable Add/Delete/Update for combinations
- GUI: Load Combinations manager dialog, Run-dialog evaluation,
  envelope display in Results panel, Combinations tab in Table dock
- tests: unit coverage (validation, math, error paths) + integration
  superposition check vs a single factored run
2026-09-11 13:19:59 -04:00

3.6 KiB
Raw Permalink Blame History

Contributing

Thanks for helping with OTKO — a SAP2000-style desktop GUI for OpenSeesPy. Early-stage project: the bar is architecture cleanliness, not feature count. If your change breaks a layering rule below, it won't merge — no matter how useful the feature.

Dev setup

python -m venv .venv
source .venv/bin/activate           # Linux / macOS
# .venv\Scripts\activate            # Windows
pip install -e ".[gui,dev]"
pre-commit install

pip install -e ".[gui,dev]" pulls the Qt/PyVista desktop stack plus the dev tools. For a headless checkout (core + services only, no Qt) use pip install -e . instead. Python 3.10+; on Windows use 3.12+.

Launch the GUI with:

python -m otko

pre-commit install wires ruff + mypy into your local git hooks so obvious issues are caught before a commit. Run it once per clone.

Before opening a PR

Run the verify commands in this order and make sure they are all clean:

ruff check src tests
ruff format src tests          # line-length 100, E501 ignored
mypy src/otko/core src/otko/services
pytest -m "not slow"           # CI gate: lint → this, on 3.10/3.11/3.12 × ubuntu/windows/macos

Focused runs are faster while iterating: pytest tests/unit (pure logic, milliseconds), pytest tests/gui -k <name> (pytest-qt, needs a display; Linux GUI tests want xvfb-run -a pytest ...), and pytest tests/integration -k <name> (real OpenSeesPy runs). Single test: pytest tests/unit/test_project.py::test_name -q. Markers: gui, slow.

Architectural rules (enforced in review)

OTKO uses a strict one-way MVVM + service architecture. Dependencies flow outward-in only:

views → viewmodels → services → core

commands sits alongside the bridge and owns every model mutation.

  1. core/ is pure Python — stdlib + numpy + pydantic. It may not import Qt or openseespy. Period.
  2. services/ may use core + h5py + openseespy, but may not import Qt.
  3. views/ (PySide6/pyvistaqt) may not import openseespy directly — go through a service. No business logic in views.
  4. viewmodels/ bridges core ↔ Qt (signals, QUndoStack).
  5. commands/ holds the QUndoCommand subclasses; all model mutations go through commands, not ad-hoc edits in views.
  6. Public functions and methods need type hints and a docstring.
  7. New domain entities go through Pydantic validation.
  8. Long-running operations (>50 ms) run off the GUI thread (AnalysisWorker in a QThread, cancelled via isInterruptionRequested(); results cross threads as a lightweight ResultsHandle written to HDF5).

The full package map and the fixed OpenSeesPy command order the runner emits live in docs/architecture.md. Never reorder the runner's commands.

Branch model

main is the default and integration branch. Work on short-lived topic branches cut from main — feat/<topic>, fix/<topic>, or docs/<topic> — and open a pull request against main. Do not commit directly to main from an agent session. There is no develop branch.

Commit style

Conventional Commits — feat:, fix:, refactor:, docs:, test:, chore:, ci:. Keep each commit focused; a feat: commit should add a feature, not mix one in with unrelated refactors.

Documentation

If your change is user-visible, update docs/QUICK_GUIDE.md and the relevant roadmap or ADR entry. Project model files are .osmodel (Pydantic-validated JSON); regenerate the checked-in examples/*.osmodel from their scripts with python examples/<name>.py rather than hand-editing them.