From 2cc04c1edc8897f5921853e88924159b54d548c1 Mon Sep 17 00:00:00 2001 From: PandaHUN777 <117030640+PandaHUN777@users.noreply.github.com> Date: Fri, 25 Sep 2026 23:18:20 +0200 Subject: [PATCH 1/3] docs: add dataset-label draft examples --- CHANGELOG.md | 2 ++ examples/drafts/dataset_label_reference.yaml | 35 +++++++++++++++++++ .../dataset_label_training_unreviewed.yaml | 35 +++++++++++++++++++ tests/test_draft.py | 27 ++++++++++++-- tools/check_distribution.py | 9 +++-- 5 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 examples/drafts/dataset_label_reference.yaml create mode 100644 examples/drafts/dataset_label_training_unreviewed.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index c0f7186..5985ff4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ - Add `community/profiles/`: contributed domain profiles whose example cases are built, validated and checked against expected outcomes in CI; `_template/` to copy. - Add a documentation site (MkDocs, strict link checking) published to GitHub Pages. +- Add admitted and rejected `dataset-label` draft examples, covered by draft and + installed-wheel checks. - The canine 0.3 implementation is also preserved at the `canine-0.3` tag. - No change to validation decisions or report format; both benchmarks reproduce 0.6.0 exactly apart from `validator_version`. diff --git a/examples/drafts/dataset_label_reference.yaml b/examples/drafts/dataset_label_reference.yaml new file mode 100644 index 0000000..1925d2b --- /dev/null +++ b/examples/drafts/dataset_label_reference.yaml @@ -0,0 +1,35 @@ +# Synthetic dataset-label draft admitted for reference annotation. +# Build: bioevidence build examples/drafts/dataset_label_reference.yaml --output record.json +# Validate: bioevidence validate record.json --profile dataset-label (exit 0: admitted) +profile: dataset-label +uses: [reference_annotation] + +statement: + subject: {id: "SYN:SAMPLE_A", label: Synthetic sample A, type: sample} + predicate: has_label + object: {id: "SYN:LABEL_A", label: Synthetic class A, type: class_label} + scope: ["cohort:synthetic"] + +sources: + - id: labels + title: Synthetic label table; not real biological evidence + type: dataset_snapshot + uri: https://example.org/synthetic-labels + version: synthetic-v1 + retrieved_at: "2026-09-25T00:00:00Z" + sha256: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +evidence: + - source: labels + locator: row-1-label + text: Synthetic sample A has synthetic class A. + type: curated_label + method: manual_curation + scope: ["cohort:synthetic"] + + - source: labels + locator: row-1-link + text: Synthetic sample A is linked to row 1 of the label table. + type: sample_link + method: deterministic_parser + scope: ["cohort:synthetic"] diff --git a/examples/drafts/dataset_label_training_unreviewed.yaml b/examples/drafts/dataset_label_training_unreviewed.yaml new file mode 100644 index 0000000..f5a81d9 --- /dev/null +++ b/examples/drafts/dataset_label_training_unreviewed.yaml @@ -0,0 +1,35 @@ +# Synthetic dataset-label draft rejected for training use without human acceptance. +# Build: bioevidence build examples/drafts/dataset_label_training_unreviewed.yaml --output record.json +# Validate: bioevidence validate record.json --profile dataset-label (exit 1: rejected) +profile: dataset-label +uses: [training_data] + +statement: + subject: {id: "SYN:SAMPLE_A", label: Synthetic sample A, type: sample} + predicate: has_label + object: {id: "SYN:LABEL_A", label: Synthetic class A, type: class_label} + scope: ["cohort:synthetic"] + +sources: + - id: labels + title: Synthetic label table; not real biological evidence + type: dataset_snapshot + uri: https://example.org/synthetic-labels + version: synthetic-v1 + retrieved_at: "2026-09-25T00:00:00Z" + sha256: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +evidence: + - source: labels + locator: row-1-label + text: Synthetic sample A has synthetic class A. + type: curated_label + method: manual_curation + scope: ["cohort:synthetic"] + + - source: labels + locator: row-1-link + text: Synthetic sample A is linked to row 1 of the label table. + type: sample_link + method: deterministic_parser + scope: ["cohort:synthetic"] diff --git a/tests/test_draft.py b/tests/test_draft.py index 1a5f4af..fa6346b 100644 --- a/tests/test_draft.py +++ b/tests/test_draft.py @@ -39,6 +39,19 @@ def test_reviewed_draft_is_admitted_for_both_uses(): assert overall == "admitted" and uses == {"research_summary": "admitted", "knowledge_base": "admitted"} +def test_dataset_label_reference_draft_is_admitted(): + overall, uses, _ = statuses(draft("dataset_label_reference.yaml")) + assert overall == "admitted" + assert uses == {"reference_annotation": "admitted"} + + +def test_dataset_label_training_draft_requires_human_acceptance(): + overall, uses, report = statuses(draft("dataset_label_training_unreviewed.yaml")) + assert overall == "rejected" + assert uses == {"training_data": "rejected"} + assert {f["rule_id"] for f in report["findings"]} == {"BEV010"} + + def test_build_expands_structure_and_hashes_local_file(): record = build(draft()) source, = record["source_artifacts"] @@ -138,9 +151,17 @@ def test_draft_schema_is_valid_json_schema(profile): assert schema["properties"]["profile"] == {"const": profile} -@pytest.mark.parametrize("name", ["llm_claim.yaml", "reviewed_claim.yaml"]) -def test_example_drafts_match_their_profile_schema(name): - Draft202012Validator(draft_json_schema("literature-claim")).validate(draft(name)) +@pytest.mark.parametrize( + "name,profile", + [ + ("llm_claim.yaml", "literature-claim"), + ("reviewed_claim.yaml", "literature-claim"), + ("dataset_label_reference.yaml", "dataset-label"), + ("dataset_label_training_unreviewed.yaml", "dataset-label"), + ], +) +def test_example_drafts_match_their_profile_schema(name, profile): + Draft202012Validator(draft_json_schema(profile)).validate(draft(name)) def test_draft_schema_turns_profile_allowlists_into_enums(): diff --git a/tools/check_distribution.py b/tools/check_distribution.py index c938124..46af654 100644 --- a/tools/check_distribution.py +++ b/tools/check_distribution.py @@ -44,10 +44,15 @@ def run(*args, expected=0): run("generate-schema", "--output", output) assert "BioEvidenceRecord" in json.loads(output.read_text(encoding="utf-8"))["$defs"] with tempfile.TemporaryDirectory() as directory: - for draft, expected in [("llm_claim.yaml", 2), ("reviewed_claim.yaml", 0)]: + for draft, profile, expected in [ + ("llm_claim.yaml", "literature-claim", 2), + ("reviewed_claim.yaml", "literature-claim", 0), + ("dataset_label_reference.yaml", "dataset-label", 0), + ("dataset_label_training_unreviewed.yaml", "dataset-label", 1), + ]: output = Path(directory) / (draft + ".json") run("build", root / "examples/drafts" / draft, "--output", output) - run("validate", output, "--profile", "literature-claim", expected=expected) + run("validate", output, "--profile", profile, expected=expected) schema = json.loads(run("draft-schema", "--profile", "literature-claim").stdout) assert schema["properties"]["profile"] == {"const": "literature-claim"} record = json.loads((root / "examples/general/curated_assertion.json").read_text(encoding="utf-8")) From 8d859da970502ce9544c8a203ce3c7d6bedb869f Mon Sep 17 00:00:00 2001 From: PandaHUN777 <117030640+PandaHUN777@users.noreply.github.com> Date: Sat, 26 Sep 2026 15:05:23 +0200 Subject: [PATCH 2/3] test(ci): scope literature-claim draft glob to claim files --- .github/workflows/ci.yml | 2 +- tests/test_github_action.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1723510..8473da7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,7 @@ jobs: id: drafts uses: ./ with: - files: examples/drafts/*.yaml + files: examples/drafts/*claim.yaml profile: literature-claim format: draft fail-on: rejected diff --git a/tests/test_github_action.py b/tests/test_github_action.py index c0bdfd2..54374af 100644 --- a/tests/test_github_action.py +++ b/tests/test_github_action.py @@ -22,7 +22,7 @@ def run(monkeypatch, tmp_path, *args): @pytest.mark.parametrize("fail_on,expected", [("review", 1), ("rejected", 0)]) def test_drafts_fail_on_review_only_when_asked(monkeypatch, tmp_path, fail_on, expected): - code, summary, counts = run(monkeypatch, tmp_path, "--files", "examples/drafts/*.yaml", + code, summary, counts = run(monkeypatch, tmp_path, "--files", "examples/drafts/*claim.yaml", "--profile", "literature-claim", "--format", "draft", "--fail-on", fail_on) assert code == expected assert counts == {"admitted": 1, "review_required": 1, "rejected": 0, "error": 0} From b1191500444a724bcccc345f5fc544c25d0392b1 Mon Sep 17 00:00:00 2001 From: PandaHUN777 <117030640+PandaHUN777@users.noreply.github.com> Date: Tue, 29 Sep 2026 03:39:22 +0200 Subject: [PATCH 3/3] docs: move dataset-label changelog entry --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5985ff4..4780097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- Add admitted and rejected `dataset-label` draft examples, covered by draft and + installed-wheel checks. + ## 0.7.0 — Expert review, quality checks, community and documentation site - Add `bioevidence review` (`check`, `agreement`, `adjudication-sheet`, `score`, `freeze`) @@ -18,8 +21,6 @@ - Add `community/profiles/`: contributed domain profiles whose example cases are built, validated and checked against expected outcomes in CI; `_template/` to copy. - Add a documentation site (MkDocs, strict link checking) published to GitHub Pages. -- Add admitted and rejected `dataset-label` draft examples, covered by draft and - installed-wheel checks. - The canine 0.3 implementation is also preserved at the `canine-0.3` tag. - No change to validation decisions or report format; both benchmarks reproduce 0.6.0 exactly apart from `validator_version`.