Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/medharness-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ runs:

- name: Install medharness
shell: bash
run: pip install "medharness${{ inputs.extras }}==0.9.0"
run: pip install "medharness${{ inputs.extras }}==0.10.0"
20 changes: 10 additions & 10 deletions .github/workflows/ci-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ jobs:

- name: Run DHF validation
run: |
medharness ci dhf-validate \
medharness verify dhf \
--dhf DHF \
--run-schema \
--run-traceability \
Expand Down Expand Up @@ -252,7 +252,7 @@ jobs:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
CR_ID=$(echo "${{ github.event.pull_request.head.ref }}" | grep -oE 'CR-[0-9]+')
if ! medharness --dhf DHF ci validate-branch \
if ! medharness --dhf DHF verify branch \
--cr "$CR_ID" \
--code-path apps/ \
--code-path packages/; then
Expand All @@ -267,7 +267,7 @@ jobs:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
CR_ID=$(echo "${{ github.event.pull_request.head.ref }}" | grep -oE 'CR-[0-9]+')
if ! medharness --dhf DHF ci validate-code \
if ! medharness --dhf DHF verify code \
--cr "$CR_ID"; then
gh pr comment "$PR_NUMBER" --body \
"⚠️ **Test annotation check failed** for $CR_ID — one or more items in \`test_plan.needs_new_tc\` are missing \`@links:<ID>\` annotations. See CI logs for details."
Expand Down Expand Up @@ -535,7 +535,7 @@ jobs:

- name: Run requirement-test coverage gate
run: |
medharness ci test-coverage \
medharness verify tests \
--dhf DHF \
--junit-dir test-results/srs \
--junit-dir test-results/srs-api \
Expand All @@ -547,19 +547,19 @@ jobs:

- name: Run test-point coverage gate (TDD)
run: |
medharness ci test-points \
medharness verify tests \
--dhf DHF \
--junit-dir test-results/srs \
--junit-dir test-results/srs-api \
--junit-dir test-results/sys \
--junit-dir test-results/crs \
--req-type SRS \
--req-type SYS \
--req-type CRS
--requirement-type SRS \
--requirement-type SYS \
--requirement-type CRS

- name: Run verification completeness gate
run: |
medharness ci validate-verification \
medharness verify verification \
--dhf DHF \
--junit-dir test-results/srs \
--junit-dir test-results/srs-api \
Expand Down Expand Up @@ -625,7 +625,7 @@ jobs:

- name: Generate evidence bundle
run: |
medharness --dhf DHF ci evidence bundle \
medharness --dhf DHF evidence bundle \
--out-dir dhf-artifacts \
--traceability-type UC \
--traceability-type CRS \
Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/cr-lifecycle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
- name: Plan lifecycle action
id: plan
run: |
python -m medharness ci github-event \
python -m medharness automation github-event \
--stage-label-prefix "cr:stage/" \
--dispatch-action design=gen-code \
--dispatch-action code=code-approved \
Expand Down Expand Up @@ -115,7 +115,7 @@ jobs:
run: |
CR_ID=$(jq -r '.cr_id // ""' /tmp/event-plan.json)
PR_NUMBER="${{ github.event.pull_request.number }}"
[ -n "$CR_ID" ] && medharness --dhf DHF ci cr-status \
[ -n "$CR_ID" ] && medharness --dhf DHF change status \
--cr "$CR_ID" ${PR_NUMBER:+--pr "$PR_NUMBER"} \
--branch "${{ github.head_ref || github.ref_name }}"

Expand Down Expand Up @@ -180,7 +180,7 @@ jobs:
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
run: |
set -o pipefail
python -m medharness --dhf DHF ci generate-dhf --cr "$CR_ID" ${PR_NUMBER:+--pr "$PR_NUMBER"} | tee /tmp/generate-dhf-out.json
python -m medharness --dhf DHF change plan --cr "$CR_ID" ${PR_NUMBER:+--pr "$PR_NUMBER"} | tee /tmp/generate-dhf-out.json

- name: Upload design payload
if: always()
Expand Down Expand Up @@ -244,7 +244,7 @@ jobs:
CR_ID: ${{ needs.detect.outputs.cr_id }}
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
run: |
if ! python -m medharness ci dhf-validate \
if ! python -m medharness verify dhf \
--dhf DHF \
--run-schema \
--run-traceability \
Expand All @@ -265,7 +265,7 @@ jobs:
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
ISSUE_NUMBER: ${{ needs.detect.outputs.issue_number }}
run: |
medharness ci advance-stage \
medharness change advance \
--pr "$PR_NUMBER" \
--from-stage cr \
--to-stage design \
Expand Down Expand Up @@ -300,7 +300,7 @@ jobs:
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
run: |
set -o pipefail
python -m medharness --dhf DHF ci generate-dhf --cr "$CR_ID" --pr "$PR_NUMBER" | tee /tmp/revise-generate-dhf-out.json
python -m medharness --dhf DHF change plan --cr "$CR_ID" --pr "$PR_NUMBER" | tee /tmp/revise-generate-dhf-out.json

- name: Upload revise-design payload
if: always()
Expand Down Expand Up @@ -368,7 +368,7 @@ jobs:
CR_ID: ${{ needs.detect.outputs.cr_id }}
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
run: |
medharness ci approve-gate --cr "$CR_ID" --stage design --pr "$PR_NUMBER"
medharness approval check --cr "$CR_ID" --stage design --pr "$PR_NUMBER"
- name: Generate implementation
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
Expand All @@ -378,7 +378,7 @@ jobs:
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
run: |
set -o pipefail
python -m medharness --dhf DHF ci develop-cr --cr "$CR_ID" ${PR_NUMBER:+--pr "$PR_NUMBER"} | tee /tmp/develop-out.json
python -m medharness --dhf DHF change implement --cr "$CR_ID" ${PR_NUMBER:+--pr "$PR_NUMBER"} | tee /tmp/develop-out.json

- name: Upload develop payload
if: always()
Expand Down Expand Up @@ -436,7 +436,7 @@ jobs:
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
ISSUE_NUMBER: ${{ needs.detect.outputs.issue_number }}
run: |
medharness ci advance-stage \
medharness change advance \
--pr "$PR_NUMBER" \
--from-stage design \
--to-stage code \
Expand Down Expand Up @@ -526,7 +526,7 @@ jobs:
PR_NUMBER: ${{ needs.detect.outputs.pr_number }}
run: |
set -o pipefail
python -m medharness --dhf DHF ci develop-cr --cr "$CR_ID" --pr "$PR_NUMBER" | tee /tmp/revise-code-out.json
python -m medharness --dhf DHF change implement --cr "$CR_ID" --pr "$PR_NUMBER" | tee /tmp/revise-code-out.json

- name: Upload revise-code payload
if: always()
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/issue-to-cr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ jobs:
# No --pr here: passing --pr switches generate-dhf into revision mode
# (reads PR review feedback), which is wrong on a brand-new draft PR.
# Revision mode is only used by cr-lifecycle.yml revise-design.
python -m medharness --dhf DHF ci generate-dhf --cr "$CR_ID" | tee /tmp/generate-dhf-out.json
python -m medharness --dhf DHF change plan --cr "$CR_ID" | tee /tmp/generate-dhf-out.json

- name: Post design failure comment
if: always() && steps.open_pr.outcome == 'success' && steps.generate_design.outcome != 'success'
Expand Down
52 changes: 31 additions & 21 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@ pnpm --filter @contourlab/client typecheck # typecheck frontend
pnpm -r typecheck # typecheck all workspaces
pnpm -r build # build all workspaces

# DHF operations (Python)
# DHF operations (Python) — two CLIs: medharness (AI/CI harness) + dhfkit (data layer)
# dhfkit is bundled inside the medharness wheel; one install gets both binaries
pip install -r requirements.txt # one-time setup
medharness --dhf DHF dhf item list --type cr # list all CRs
medharness --dhf DHF dhf item get CR-NNN # get CR details
medharness --dhf DHF dhf item transition CR-NNN <state> --by "Author"
medharness --dhf DHF dhf validate schema # validate all item YAMLs
medharness --dhf DHF dhf doc generate ALL # regenerate spec documents
dhfkit --dhf DHF item list --type cr # list all CRs
dhfkit --dhf DHF item get CR-NNN # get CR details
dhfkit --dhf DHF item transition CR-NNN <state> --by "Author"
dhfkit --dhf DHF validate schema # validate all item YAMLs
dhfkit --dhf DHF doc generate ALL # regenerate spec documents
```

## Key Conventions
Expand All @@ -56,35 +57,41 @@ medharness --dhf DHF dhf doc generate ALL # regenerate spec document
- **Proxy**: Vite proxies `/api` and `/ws` → `localhost:4000`; `/dicom-web` → Orthanc `localhost:8042`
- **TypeScript**: strict mode throughout, no `any`
- **Styling**: Tailwind only, no inline styles, dark clinical theme (see `/ux-design`)
- **DHF**: DHF items live at `DHF/items/`. Use `medharness --dhf DHF dhf ...` commands. The CR
design plan lives in the `implementation_notes` field of `DHF/items/09_cr/CR-NNN.yaml`. Do not
scatter direct DHF file reads across automation — use the `medharness` CLI facade.
- **DHF**: DHF items live at `DHF/items/`. Use `dhfkit --dhf DHF ...` for data operations (CRUD,
validate, doc generate) and `medharness --dhf DHF ...` for AI/CI harness operations (context,
change status, approval). The CR design plan lives in the `implementation_notes` field of
`DHF/items/09_cr/CR-NNN.yaml`. Do not scatter direct DHF file reads across automation — use
the CLI facade.

### DHF Facade API Quick Reference

```bash
# --- medharness: AI/CI harness commands ---

# Get CR implementation context (spec + DHF overview) for AI/CI consumption
medharness --dhf DHF dhf context implementation --cr CR-034 --out-dir /tmp/cr-context

# Get scoped context for a specific workflow stage (analyze / design / develop)
# Get scoped context for a specific workflow stage (stage: analyze | design | develop)
medharness --dhf DHF dhf context for-stage develop --cr CR-034

# Check CR stage and approval status (machine-readable JSON)
medharness --dhf DHF change status --cr CR-034 --pr 42

# --- dhfkit: DHF data-layer commands ---

# Print human-readable traceability coverage report
medharness --dhf DHF dhf report
dhfkit --dhf DHF report

# Validate DHF schema and traceability locally
medharness --dhf DHF dhf validate schema
medharness --dhf DHF dhf validate traceability

# Check CR stage and approval status (machine-readable JSON)
medharness --dhf DHF ci cr-status --cr CR-034 --pr 42
dhfkit --dhf DHF validate schema
dhfkit --dhf DHF validate traceability

# Transition a CR
medharness --dhf DHF dhf item transition CR-034 completed --by "agent"
dhfkit --dhf DHF item transition CR-034 completed --by "agent"

# List and inspect items
medharness --dhf DHF dhf item get SRS-001
medharness --dhf DHF dhf item list --type SRS
dhfkit --dhf DHF item get SRS-001
dhfkit --dhf DHF item list --type SRS
```

## Sources of Truth
Expand Down Expand Up @@ -139,7 +146,10 @@ Design and implementation live on the same branch, each committed separately.

3. **Tests** — write alongside every functional change: unit tests for pure logic, component
tests for React components, regression tests for bug fixes. Colocate at `*.test.ts(x)`.
Add `@links:SRS-xxx` or `@links:SYS-xxx` annotations to tests that verify DHF requirements.
- Add `@links:SRS-xxx` or `@links:SYS-xxx` annotations to tests that verify DHF requirements.
- For numbered test points (`T1:`, `T2:` on a requirement): embed `@testing:T1` in the test
name (JS/TS) or use `@pytest.mark.dhf_testing("T1")` (Python) so the CI gate
`medharness verify tests` can confirm every test point has passing coverage.
4. **Design** — `generate-dhf` writes the implementation plan into the CR item's
`implementation_notes`; treat that as the primary input for `develop-cr`. Invoke
`/ux-design` before any UI work.
Expand All @@ -150,7 +160,7 @@ Design and implementation live on the same branch, each committed separately.
pnpm --filter @contourlab/client lint && pnpm --filter @contourlab/client typecheck
dotnet build apps/api/api.csproj --configuration Release # API changes
pnpm -r typecheck # data model changes
medharness --dhf DHF dhf validate schema # DHF item changes
dhfkit --dhf DHF validate schema # DHF item changes
```
7. **Handoff** — run `/post-implement`; open PR with CR ID in title, change summary,
DHF files updated, validation run, manual test plan.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"scripts": {
"dev": "pnpm --filter @contourlab/client dev",
"api": "cd apps/api && dotnet run --launch-profile http",
"autocontour:service": "cd apps/autocontour-service && uvicorn main:app --host 127.0.0.1 --port 4010 --reload",
"autocontour:service": "cd apps/autocontour-service && .venv/bin/python -m uvicorn main:app --host 127.0.0.1 --port 4010 --reload",
"repo:up": "docker compose up -d dicom-repo",
"repo:down": "docker compose down",
"repo:logs": "docker compose logs -f dicom-repo",
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
medharness[full]==0.9.0
medharness[full]==0.10.0
Loading