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.6.2.tar.gz (144.5 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.6.2-py3-none-any.whl (183.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for medharness-0.6.2.tar.gz
Algorithm Hash digest
SHA256 465c12e9370c9a84ba407e367171f573f2139d206fa25f8efe2598a220fbdc79
MD5 88023372deec3737d683cdaebf5370e9
BLAKE2b-256 dd507bf0cca9a7204b6febe50ccf3ce60b188ff6c06f6a23d0fa678c5f0750ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for medharness-0.6.2.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.6.2-py3-none-any.whl.

File metadata

  • Download URL: medharness-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 183.9 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.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7cf118b4a09a3fbc661cafb498d3e35ef3e6ef3f0fe0deed68819fa8d5a313fa
MD5 fc50455dc4dda932f917e1e0b0583e24
BLAKE2b-256 8218ce4dc2afd0837ff63e704ff59e2b524151168b2fee730998baa32e812b9d

See more details on using hashes here.

Provenance

The following attestation bundles were made for medharness-0.6.2-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