Skip to content

Coding standards

Enforced on every task in the local MVP lane.

Rules

Rule Meaning
Atomic functions One responsibility; ~30 lines max
Chunk + test pytest green before next task
Protocols typing.Protocol for parsers — no vendor imports in core/
Registry Plugins register in plugins/__init__.py only
Stable contracts Return core/models.py types from all plugins
Fail closed Missing creds → enabled=False, never silent wrong API
No PHI in logs Log job_id, parser_id, confidence only
Never drop an analyte Extra LLM processing is fine; a missing lab value is not. Every row a stage does not keep is named in the extraction funnel and, when uncoded, in /loinc-review

UI rules (no build step)

Rule Meaning
One shell Pages are composed by web/pages.py::render_page from static/_shell.html + static/pages/<name>.html; the nav is NAV_ITEMS. No inline scripts or style="" in fragments
Modules with init() Every page script is an ES module importing static/common.js and exporting init(), guarded by if (typeof document !== "undefined") init(); so Node can import it
Escape at the render boundary Every value that reaches innerHTML goes through escapeHtml inside a builder in *-format.js; the page module only assigns builder output (tests/test_faxes_static.py guards this)
Pure formatters under node --test Labels, validation and HTML builders live in review-format.js, faxes-format.js, harness-format.js and are tested in tests/web/*.test.mjs (bridged into pytest by tests/test_web_assets.py); each HTML builder is fed <x>
One vocabulary Decisions, scopes, specimens, sources and outcomes have one label map each; never a raw enum on screen
Status where the person looks An inline setStatus line beside the control that was used; a toast only for page-level outcomes; never alert/confirm (use confirmDialog)
401 means sign in and come back api() redirects to /login?next=…; never show raw JSON to the person

Test layout

tests/
  test_core_models.py
  test_registry.py
  test_plugins_gcp.py      # @pytest.mark.gcp skips without creds
  test_orchestrator.py
  test_api.py
  test_elation_adapter.py
  test_web_pages.py        # shell composition, headers
  test_web_assets.py       # node --test bridge, module imports, one owner per helper, CSS tokens
  test_faxes_static.py     # innerHTML source guard, builders have a Node escape test
  web/*.test.mjs           # node:test — pure page logic

Adding code checklist

  1. Implement smallest unit
  2. Write test
  3. Run pytest
  4. Update MkDocs page for the area you changed
  5. Entry in .cursor/memory/CHANGELOG.md (no PHI)