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.
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
- docs/architecture.md — packages, scaffold model, DHF lifecycle
- docs/compatibility-contracts.md — stable public contracts
- docs/adr/ — architecture decision records
- CHANGELOG.md — version history
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file medharness-0.6.0.tar.gz.
File metadata
- Download URL: medharness-0.6.0.tar.gz
- Upload date:
- Size: 143.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5ebbe058aa5b845b273ae357b61370ba11479569cad44d4634c528a262d9b17
|
|
| MD5 |
3ac1ae08b600ff197bdc23048ba817ce
|
|
| BLAKE2b-256 |
f368698290fb608fc8659efa9c7889b2f7ad9267156de0c35da90fc7fdc0f4ff
|
Provenance
The following attestation bundles were made for medharness-0.6.0.tar.gz:
Publisher:
release.yml on itercharles/MedHarness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
medharness-0.6.0.tar.gz -
Subject digest:
a5ebbe058aa5b845b273ae357b61370ba11479569cad44d4634c528a262d9b17 - Sigstore transparency entry: 1549935091
- Sigstore integration time:
-
Permalink:
itercharles/MedHarness@f0122938ee2e499e215878f0128a93d00fe83c29 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/itercharles
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f0122938ee2e499e215878f0128a93d00fe83c29 -
Trigger Event:
push
-
Statement type:
File details
Details for the file medharness-0.6.0-py3-none-any.whl.
File metadata
- Download URL: medharness-0.6.0-py3-none-any.whl
- Upload date:
- Size: 183.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
474b3a9d4ba6b06c1feeccd8b48e2cdf43bb18f0c2eac4b43e9173d5404c4758
|
|
| MD5 |
80d1ffee26034d76f43fea23ee3cda32
|
|
| BLAKE2b-256 |
b605137bd75f96e479b80b8fb427cbe1795eceb65f99ce27d5478a21b30a21f3
|
Provenance
The following attestation bundles were made for medharness-0.6.0-py3-none-any.whl:
Publisher:
release.yml on itercharles/MedHarness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
medharness-0.6.0-py3-none-any.whl -
Subject digest:
474b3a9d4ba6b06c1feeccd8b48e2cdf43bb18f0c2eac4b43e9173d5404c4758 - Sigstore transparency entry: 1549935227
- Sigstore integration time:
-
Permalink:
itercharles/MedHarness@f0122938ee2e499e215878f0128a93d00fe83c29 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/itercharles
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f0122938ee2e499e215878f0128a93d00fe83c29 -
Trigger Event:
push
-
Statement type: