Skip to main content

Open-source design-controlled development infrastructure for medical device and SaMD teams — includes dhfkit

Project description

MedHarness

Design-controlled AI development for medical device software.

PyPI License: MIT Python 3.11+


What this is

Building software for a medical device means every requirement, risk, architectural decision, and test has to be traced and documented in a Design History File (DHF) — before code ships, and in a form that holds up under FDA or notified body scrutiny.

That's a real documentation burden. Teams spend meaningful engineering time on traceability matrices, impact assessments, and evidence bundles — work that doesn't ship features but is genuinely required to ship regulated products.

MedHarness makes that work AI-assisted without making it ungoverned. It gives Claude a structured role in your DHF workflow — generating design items, implementing code — while keeping you in the loop at every approval gate. The agent executes; you decide when to advance.


How it works

Every non-trivial change flows through a Change Request (CR) in the DHF. MedHarness runs Claude in two phases, validates the output deterministically, and opens a PR for your review before anything moves forward.

Phase 1 — Design (generate-dhf)

Claude reads the CR, triages it (duplicate? out-of-scope? too large?), then reads the relevant source modules and reasons top-down through the V-model hierarchy:

CR → CRS → SYS → { SYSARCH, RISK, RCM } → SRS → SWDD

It writes DHF items via the CLI, validates schema and traceability inline, and finally produces a detailed implementation plan in implementation_notes on the CR item. A PR opens for your review — you see the design items and the implementation plan before any code is written.

Phase 2 — Implementation (develop-cr)

After the design PR is approved, Claude reads implementation_notes and the linked DHF items, implements the code, annotates tests with @links: requirement IDs, runs medharness ci test-coverage to verify every requirement has a passing test, and reconciles any deviations back onto implementation_notes and the SWDD items.

At each phase, MedHarness pre-computes DHF context — item lists, traceability graph, coverage gaps — and injects it into Claude's prompt so the agent reasons about your actual DHF rather than guessing. After Claude runs, a deterministic validator checks schema, traceability links, and test annotations, and self-corrects if it can.


Who it's for

  • Medical device software teams working under IEC 62304, FDA 21 CFR 820.30, or MDR who want AI help that doesn't bypass the process
  • Platform / DevOps engineers building regulated CI pipelines who need programmatic hooks into DHF validation and evidence generation
  • Startups bootstrapping a DHF alongside their product without a dedicated RA team writing everything by hand

dhfkit — the DHF engine inside MedHarness — also works standalone if you only need YAML-based item storage, traceability graphs, and document generation without the full CR workflow.


Install

pip install medharness[full]

[full] includes optional extras: ai (AI review) and docs (PDF export via WeasyPrint). Leave it off for a minimal install — dhfkit is always included either way.

medharness --help
dhfkit --help

From source:

git clone https://github.com/itercharles/MedHarness
cd MedHarness
pip install -e ".[dev]"
pytest dhfkit/tests/ tests/

Quick start

medharness init scaffolds a complete DHF project in the current directory — no prompts, nothing to fill out:

mkdir my-device && cd my-device
python -m venv .venv && source .venv/bin/activate
pip install medharness
medharness init

You get a working DHF with sample requirements, risks, traceability config, document templates, and plans — ready to replace with your real content:

my-device/
├── DHF/
│   ├── config/           # project name, lifecycle states, doc type schemas
│   ├── items/            # one YAML file per requirement, risk, CR, etc.
│   │   ├── 01_crs/       # Customer Requirements
│   │   ├── 02_sys/       # System Requirements
│   │   ├── 03_srs/       # Software Requirements
│   │   ├── 06_cr/        # Change Requests
│   │   └── ...           # Use Cases, SOUP, Risk, RCM, Defects
│   ├── documents/        # Jinja2 spec templates and plan documents
│   └── test-results/
├── CLAUDE.md             # AI agent entrypoint
└── README.md

Then push it to git and you're tracking your DHF from day one:

git init && git add -A && git commit -m "feat: initialize DHF"

The CR workflow in practice

# Phase 1 — Claude triages the CR, generates DHF items, and writes an
# implementation plan. Opens a PR for design review.
medharness --dhf DHF ci generate-dhf --cr CR-034

# Phase 2 — after the design PR is approved, Claude implements the code,
# verifies test coverage, and reconciles any deviations back onto the DHF.
medharness --dhf DHF ci develop-cr --cr CR-034

Claude reasons top-down through the V-model during design, reading relevant source modules before writing SWDD items so the reviewed design reflects the actual codebase. The implementation plan in implementation_notes is the handoff artifact — it drives the develop phase without re-deriving the design.

Got review comments on a design PR? Pass --pr N to revise based on the feedback:

medharness --dhf DHF ci generate-dhf --cr CR-034 --pr 42

ANTHROPIC_MODEL selects the Claude model. GH_TOKEN is required when using --pr.

Each command outputs structured JSON with outcome, errors, timing, and artifact paths — so CI automation can act on results without parsing text.


CR lifecycle

A CR moves through these states automatically as the workflow progresses:

State Meaning
new CR created, awaiting design
design generate-dhf has run; design PR open for review
develop Design approved; develop-cr has run; code PR open
completed Code PR merged
rejected Triage determined the CR is out-of-scope, duplicate, or too large

The auto workflow does not enforce state transitions as gates — generate-dhf and develop-cr can run regardless of the current state. States are recorded for traceability and audit, not for blocking automation.


CI gates

Three gates you'd typically run before a PR merges:

DHF schema and traceability

medharness ci dhf-validate --dhf DHF

Validates item schemas, required fields, and traceability links across the entire DHF.

Requirement-to-test coverage

medharness ci test-coverage --dhf DHF --junit-dir test-results

Reads JUnit XML test results and checks that every verifiable requirement has at least one linked passing test. Tests link to DHF items via @links:<ITEM_ID> annotations in their source, surfaced through JUnit properties. Exits non-zero when gaps exist.

Evidence bundle

medharness ci evidence bundle --dhf DHF --out-dir artifacts --junit-dir test-results

Produces a timestamped DHF snapshot and test evidence archive on merge to main.


Automation model

MedHarness ships no prescribed CI workflow files — the stable interface is the CLI. Wire it into whatever automation layer fits your team (GitHub Actions, GitLab CI, Jenkins, local scripts):

# DHF operations
medharness --dhf DHF dhf item list --type SYS
medharness --dhf DHF dhf validate schema
medharness --dhf DHF dhf validate traceability
medharness --dhf DHF dhf doc generate SYS
medharness --dhf DHF dhf doc export SYS        # PDF (requires [docs])

# CR workflow
medharness cr workflow intake-github-issue-ci
medharness cr workflow complete-from-github-pr

# CR generation (AI-assisted)
medharness --dhf DHF ci generate-dhf --cr CR-034
medharness --dhf DHF ci develop-cr --cr CR-034

# CI gates
medharness ci dhf-validate --dhf DHF
medharness ci test-coverage --dhf DHF --junit-dir test-results
medharness ci evidence bundle --dhf DHF --out-dir artifacts
medharness --dhf DHF ci validate-code --cr CR-034
medharness --dhf DHF ci validate-branch --cr CR-034

# Status surface (machine-readable, for automation routing)
medharness ci cr-status --cr CR-034 --stage design --pr 18
medharness ci github-event --event "$GITHUB_EVENT_PATH"

Python API

from medharness.client import DHFClient

client = DHFClient(Path("DHF"))
cr   = client.get_item("CR-034")
client.transition_item("CR-034", "completed", performed_by="alice")

dhfkit standalone — no dependency on medharness:

from dhfkit.local_adapter import LocalDHFAdapter

adapter = LocalDHFAdapter(Path("DHF"))
items   = adapter.list_items("SRS")

Repository layout

Directory Purpose
medharness/ CLI harness, CI gates, CR workflows, init scaffolding
dhfkit/ DHF engine: items, lifecycle, traceability, document generation
dhfkit/templates/ Starter DHF scaffold — config, specs, plans, sample items
tests/ MedHarness and dhfkit test suites
docs/ Architecture, ADRs, compatibility contracts

dhfkit has no dependency on medharness and can be used on its own.


Docs


License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

medharness-0.5.0.tar.gz (137.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

medharness-0.5.0-py3-none-any.whl (176.1 kB view details)

Uploaded Python 3

File details

Details for the file medharness-0.5.0.tar.gz.

File metadata

  • Download URL: medharness-0.5.0.tar.gz
  • Upload date:
  • Size: 137.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for medharness-0.5.0.tar.gz
Algorithm Hash digest
SHA256 3dad39ff2478867015c460e89690c04560b71b0261a53e7030f115bef08a3edb
MD5 fa9c245fcacb98f58f896e1f8de969ef
BLAKE2b-256 c3e7a1fcfffdabd2488a533e561ed24ea22bc16384b90d12c3b682c5a039b735

See more details on using hashes here.

Provenance

The following attestation bundles were made for medharness-0.5.0.tar.gz:

Publisher: release.yml on itercharles/MedHarness

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file medharness-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: medharness-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 176.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for medharness-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 838e4b9c7a05c1ece476d534ef4f43e4e7eaac3f38a8afc6b881a402737a6b36
MD5 755fb1769809a9a7f828e12847e98055
BLAKE2b-256 3a75a9bbcb79423ea80e1558b3e15a2df9cc6f8b89f5e7ea647c44626a81a7d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for medharness-0.5.0-py3-none-any.whl:

Publisher: release.yml on itercharles/MedHarness

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page