scholion 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scholion-0.1.2/.gitignore +24 -0
- scholion-0.1.2/ASSISTANT-RULES.md +165 -0
- scholion-0.1.2/ATTRIBUTION.md +126 -0
- scholion-0.1.2/CHANGELOG.md +219 -0
- scholion-0.1.2/CITATION.cff +37 -0
- scholion-0.1.2/CONTRIBUTING.md +91 -0
- scholion-0.1.2/DISCLAIMER.md +74 -0
- scholion-0.1.2/LICENSE +202 -0
- scholion-0.1.2/LICENSE-DATA +55 -0
- scholion-0.1.2/NOTICE +65 -0
- scholion-0.1.2/PKG-INFO +542 -0
- scholion-0.1.2/README.md +501 -0
- scholion-0.1.2/SECURITY.md +124 -0
- scholion-0.1.2/THREAT_MODEL.md +120 -0
- scholion-0.1.2/VERSION +1 -0
- scholion-0.1.2/pyproject.toml +141 -0
- scholion-0.1.2/run_tests.sh +56 -0
- scholion-0.1.2/src/ingest/.gitkeep +0 -0
- scholion-0.1.2/src/ingest/README_track2.md +59 -0
- scholion-0.1.2/src/ingest/_sample.py +20 -0
- scholion-0.1.2/src/ingest/_sample.sh +19 -0
- scholion-0.1.2/src/ingest/acmg_sf_scan.py +201 -0
- scholion-0.1.2/src/ingest/ancestry_check.py +175 -0
- scholion-0.1.2/src/ingest/annotate_clinvar.sh +118 -0
- scholion-0.1.2/src/ingest/auto_full_vcf.sh +75 -0
- scholion-0.1.2/src/ingest/build_clinical_bed.py +103 -0
- scholion-0.1.2/src/ingest/build_longevity_sites.py +104 -0
- scholion-0.1.2/src/ingest/build_longevitymap.py +159 -0
- scholion-0.1.2/src/ingest/call_full_vcf.sh +91 -0
- scholion-0.1.2/src/ingest/clinvar_diff.py +100 -0
- scholion-0.1.2/src/ingest/csq_lof_scan.sh +270 -0
- scholion-0.1.2/src/ingest/deepvariant_call.sh +83 -0
- scholion-0.1.2/src/ingest/draw_checklist.py +434 -0
- scholion-0.1.2/src/ingest/extract_pgx_loci.sh +89 -0
- scholion-0.1.2/src/ingest/fastq_to_vcf.sh +143 -0
- scholion-0.1.2/src/ingest/first_run_check.py +213 -0
- scholion-0.1.2/src/ingest/hla_typing.sh +134 -0
- scholion-0.1.2/src/ingest/ingest_garmin.py +302 -0
- scholion-0.1.2/src/ingest/loci_sites_bed.py +55 -0
- scholion-0.1.2/src/ingest/longevity_findings_build.py +271 -0
- scholion-0.1.2/src/ingest/longevity_report.py +205 -0
- scholion-0.1.2/src/ingest/mtdna_haplogroup.sh +116 -0
- scholion-0.1.2/src/ingest/nof1.py +528 -0
- scholion-0.1.2/src/ingest/parse_evogen_pdf.py +161 -0
- scholion-0.1.2/src/ingest/parse_health_export.py +129 -0
- scholion-0.1.2/src/ingest/pgx_star_alleles.sh +137 -0
- scholion-0.1.2/src/ingest/pharmcat_run.sh +78 -0
- scholion-0.1.2/src/ingest/phenoage.py +44 -0
- scholion-0.1.2/src/ingest/prs_ancestry_sensitivity.py +153 -0
- scholion-0.1.2/src/ingest/prs_diff.py +107 -0
- scholion-0.1.2/src/ingest/prs_extract_models.py +107 -0
- scholion-0.1.2/src/ingest/prs_extract_sites.py +107 -0
- scholion-0.1.2/src/ingest/prs_genotype_sites.sh +44 -0
- scholion-0.1.2/src/ingest/prs_model_review.py +83 -0
- scholion-0.1.2/src/ingest/prs_results_build.py +225 -0
- scholion-0.1.2/src/ingest/prs_top_audit.py +103 -0
- scholion-0.1.2/src/ingest/prs_verify.py +467 -0
- scholion-0.1.2/src/ingest/qc_callability.sh +288 -0
- scholion-0.1.2/src/ingest/qc_tstv.sh +22 -0
- scholion-0.1.2/src/ingest/quarterly_reanalysis.sh +143 -0
- scholion-0.1.2/src/ingest/recheck_from_bam.sh +21 -0
- scholion-0.1.2/src/ingest/resume_merge_call.sh +46 -0
- scholion-0.1.2/src/ingest/setup_just_prs.sh +45 -0
- scholion-0.1.2/src/ingest/sle_p100_debug.py +149 -0
- scholion-0.1.2/src/ingest/telomere_length.py +122 -0
- scholion-0.1.2/src/ingest/update_catalog.py +91 -0
- scholion-0.1.2/src/ingest/update_check.sh +34 -0
- scholion-0.1.2/src/ingest/vcf_concordance.py +138 -0
- scholion-0.1.2/src/ingest/vcf_dedup_positions.py +18 -0
- scholion-0.1.2/src/ingest/vep_lof_scan.sh +218 -0
- scholion-0.1.2/src/ingest/verify_evogen.py +196 -0
- scholion-0.1.2/src/scholion/__init__.py +28 -0
- scholion-0.1.2/src/scholion/__main__.py +5 -0
- scholion-0.1.2/src/scholion/assistant.py +431 -0
- scholion-0.1.2/src/scholion/cli.py +537 -0
- scholion-0.1.2/src/scholion/contract.py +181 -0
- scholion-0.1.2/src/scholion/core.py +1098 -0
- scholion-0.1.2/src/scholion/demo.py +711 -0
- scholion-0.1.2/src/scholion/drugsource.py +284 -0
- scholion-0.1.2/src/scholion/engine.py +2299 -0
- scholion-0.1.2/src/scholion/format.py +1082 -0
- scholion-0.1.2/src/scholion/garmin.py +174 -0
- scholion-0.1.2/src/scholion/genome.py +481 -0
- scholion-0.1.2/src/scholion/i18n/__init__.py +140 -0
- scholion-0.1.2/src/scholion/i18n/en.py +1801 -0
- scholion-0.1.2/src/scholion/i18n/ru.py +1708 -0
- scholion-0.1.2/src/scholion/import_csv.py +161 -0
- scholion-0.1.2/src/scholion/ingest_labs.py +911 -0
- scholion-0.1.2/src/scholion/ingest_studies.py +195 -0
- scholion-0.1.2/src/scholion/knowledge/acmg_sf.json +1035 -0
- scholion-0.1.2/src/scholion/knowledge/clinical_thresholds.json +193 -0
- scholion-0.1.2/src/scholion/knowledge/cpic_drug_gene.json +946 -0
- scholion-0.1.2/src/scholion/knowledge/dose_evidence.json +550 -0
- scholion-0.1.2/src/scholion/knowledge/drug_interactions.json +442 -0
- scholion-0.1.2/src/scholion/knowledge/drug_lab_monitoring.json +245 -0
- scholion-0.1.2/src/scholion/knowledge/experiment_templates.json +73 -0
- scholion-0.1.2/src/scholion/knowledge/external_tools.json +295 -0
- scholion-0.1.2/src/scholion/knowledge/lab_markers.json +9099 -0
- scholion-0.1.2/src/scholion/knowledge/lab_test_meta.json +370 -0
- scholion-0.1.2/src/scholion/knowledge/loci.json +387 -0
- scholion-0.1.2/src/scholion/knowledge/longevity_directions.json +316 -0
- scholion-0.1.2/src/scholion/knowledge/longevitymap.json +40795 -0
- scholion-0.1.2/src/scholion/knowledge/med_classes.json +640 -0
- scholion-0.1.2/src/scholion/knowledge/penetrance.json +189 -0
- scholion-0.1.2/src/scholion/knowledge/prs_models.json +508 -0
- scholion-0.1.2/src/scholion/knowledge/prs_traits.json +982 -0
- scholion-0.1.2/src/scholion/knowledge/test_rules.json +220 -0
- scholion-0.1.2/src/scholion/knowledge/units.json +232 -0
- scholion-0.1.2/src/scholion/knowledge/wearable_metrics.json +355 -0
- scholion-0.1.2/src/scholion/limits.py +288 -0
- scholion-0.1.2/src/scholion/net.py +145 -0
- scholion-0.1.2/src/scholion/ouroboros_tools.py +163 -0
- scholion-0.1.2/src/scholion/phenoage.py +204 -0
- scholion-0.1.2/src/scholion/provenance.py +207 -0
- scholion-0.1.2/src/scholion/prs.py +359 -0
- scholion-0.1.2/src/scholion/reconcile.py +319 -0
- scholion-0.1.2/src/scholion/redact.py +143 -0
- scholion-0.1.2/src/scholion/server.py +470 -0
- scholion-0.1.2/src/scholion/skill/ASSISTANT-RULES.md +165 -0
- scholion-0.1.2/src/scholion/skill/SKILL.md +1105 -0
- scholion-0.1.2/src/scholion/store.py +455 -0
- scholion-0.1.2/src/scholion/tabixlite.py +127 -0
- scholion-0.1.2/src/scholion/templates/genome/README.md +41 -0
- scholion-0.1.2/src/scholion/templates/panel-template.csv +23 -0
- scholion-0.1.2/src/scholion/templates/profile/experiments.json +9 -0
- scholion-0.1.2/src/scholion/templates/profile/health_goals.json +24 -0
- scholion-0.1.2/src/scholion/templates/profile/index.md +14 -0
- scholion-0.1.2/src/scholion/templates/profile/labs.json +13 -0
- scholion-0.1.2/src/scholion/templates/profile/medications.json +10 -0
- scholion-0.1.2/src/scholion/templates/profile/metrics.json +11 -0
- scholion-0.1.2/src/scholion/templates/profile/pharmacogenomics.json +9 -0
- scholion-0.1.2/src/scholion/tools.py +498 -0
- scholion-0.1.2/src/scholion/web/apple-touch-icon.png +0 -0
- scholion-0.1.2/src/scholion/web/chart.min.js +14 -0
- scholion-0.1.2/src/scholion/web/dna.svg +16 -0
- scholion-0.1.2/src/scholion/web/favicon-16.png +0 -0
- scholion-0.1.2/src/scholion/web/favicon-32.png +0 -0
- scholion-0.1.2/src/scholion/web/favicon.ico +0 -0
- scholion-0.1.2/src/scholion/web/favicon.png +0 -0
- scholion-0.1.2/src/scholion/web/icon.svg +21 -0
- scholion-0.1.2/src/scholion/web/index.html +1625 -0
- scholion-0.1.2/src/tools/brief_edit.py +183 -0
- scholion-0.1.2/src/tools/check_compat.py +162 -0
- scholion-0.1.2/src/tools/check_language.py +380 -0
- scholion-0.1.2/src/tools/check_staged.py +299 -0
- scholion-0.1.2/src/tools/language_baseline.json +56 -0
- scholion-0.1.2/src/tools/make_demo_profile.py +20 -0
- scholion-0.1.2/src/tools/make_shareable.py +1222 -0
- scholion-0.1.2/src/tools/nof1_quick_log.sh +58 -0
- scholion-0.1.2/src/tools/sync_rules.py +200 -0
- scholion-0.1.2/src/tools/synthetic_fixture.py +130 -0
- scholion-0.1.2/tests/.gitkeep +0 -0
- scholion-0.1.2/tests/README.md +27 -0
- scholion-0.1.2/tests/__init__.py +0 -0
- scholion-0.1.2/tests/contracts/public_contract.json +222 -0
- scholion-0.1.2/tests/fixtures/genome/tiny.vcf.gz +0 -0
- scholion-0.1.2/tests/fixtures/genome/tiny.vcf.gz.tbi +0 -0
- scholion-0.1.2/tests/fixtures/labforms/01_biochem.txt +21 -0
- scholion-0.1.2/tests/fixtures/labforms/02_cbc.txt +14 -0
- scholion-0.1.2/tests/fixtures/labforms/03_hormones.txt +12 -0
- scholion-0.1.2/tests/fixtures/labforms/04_coprogram.txt +22 -0
- scholion-0.1.2/tests/fixtures/labforms/05_dysbiosis.txt +16 -0
- scholion-0.1.2/tests/fixtures/labforms/06_english_panel.txt +30 -0
- scholion-0.1.2/tests/fixtures/labforms/expected.json +201 -0
- scholion-0.1.2/tests/fixtures/profile/experiments.json +9 -0
- scholion-0.1.2/tests/fixtures/profile/health_goals.json +8 -0
- scholion-0.1.2/tests/fixtures/profile/index.md +14 -0
- scholion-0.1.2/tests/fixtures/profile/labs.json +32 -0
- scholion-0.1.2/tests/fixtures/profile/medications.json +7 -0
- scholion-0.1.2/tests/fixtures/profile/metrics.json +8 -0
- scholion-0.1.2/tests/fixtures/profile/pharmacogenomics.json +9 -0
- scholion-0.1.2/tests/support.py +109 -0
- scholion-0.1.2/tests/test_answerability.py +645 -0
- scholion-0.1.2/tests/test_atomic_write.py +68 -0
- scholion-0.1.2/tests/test_build_audit.py +704 -0
- scholion-0.1.2/tests/test_catalogue_integrity.py +236 -0
- scholion-0.1.2/tests/test_cli_smoke.py +145 -0
- scholion-0.1.2/tests/test_compat.py +44 -0
- scholion-0.1.2/tests/test_demo_drift.py +67 -0
- scholion-0.1.2/tests/test_demo_profile.py +85 -0
- scholion-0.1.2/tests/test_external_sources.py +170 -0
- scholion-0.1.2/tests/test_external_tools.py +326 -0
- scholion-0.1.2/tests/test_genome_fixture_gate.py +245 -0
- scholion-0.1.2/tests/test_genome_render.py +104 -0
- scholion-0.1.2/tests/test_i18n.py +149 -0
- scholion-0.1.2/tests/test_lab_dir_boundary.py +332 -0
- scholion-0.1.2/tests/test_lab_parsing_baseline.py +172 -0
- scholion-0.1.2/tests/test_language_baseline.py +76 -0
- scholion-0.1.2/tests/test_licensing.py +281 -0
- scholion-0.1.2/tests/test_limits.py +246 -0
- scholion-0.1.2/tests/test_localized_fields.py +198 -0
- scholion-0.1.2/tests/test_marker_resolution.py +184 -0
- scholion-0.1.2/tests/test_marker_schema.py +174 -0
- scholion-0.1.2/tests/test_math.py +62 -0
- scholion-0.1.2/tests/test_network_inventory.py +87 -0
- scholion-0.1.2/tests/test_output_language.py +82 -0
- scholion-0.1.2/tests/test_owner_split.py +126 -0
- scholion-0.1.2/tests/test_parity.py +42 -0
- scholion-0.1.2/tests/test_pgx_script_coordinates.py +141 -0
- scholion-0.1.2/tests/test_privacy_guard.py +144 -0
- scholion-0.1.2/tests/test_radar_coverage.py +160 -0
- scholion-0.1.2/tests/test_redact.py +194 -0
- scholion-0.1.2/tests/test_repo_hygiene.py +358 -0
- scholion-0.1.2/tests/test_safety_rules.py +136 -0
- scholion-0.1.2/tests/test_series_break.py +81 -0
- scholion-0.1.2/tests/test_server_guard.py +144 -0
- scholion-0.1.2/tests/test_showcase.py +233 -0
- scholion-0.1.2/tests/test_skill_editions.py +290 -0
- scholion-0.1.2/tests/test_tls_policy.py +149 -0
- scholion-0.1.2/tests/test_unit_gate.py +318 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# The user's personal data — do NOT commit.
|
|
2
|
+
# profile/*.json and genome/* are deliberately outside git: once you fill them
|
|
3
|
+
# in, the templates from the package become your own personal data. If you need
|
|
4
|
+
# a pristine template, take it from the package archive, not from the history
|
|
5
|
+
# of the repository.
|
|
6
|
+
profile/*
|
|
7
|
+
!profile/*.md
|
|
8
|
+
genome/*
|
|
9
|
+
!genome/README.md
|
|
10
|
+
raw/
|
|
11
|
+
work/
|
|
12
|
+
archive/
|
|
13
|
+
*._stale*/
|
|
14
|
+
*.vcf*
|
|
15
|
+
*.bam
|
|
16
|
+
*.pdf
|
|
17
|
+
# …except the synthetic test fixture: a few invented lines, checked by
|
|
18
|
+
# content at commit time and at build time (src/tools/synthetic_fixture.py).
|
|
19
|
+
!tests/fixtures/genome/*.vcf.gz
|
|
20
|
+
!tests/fixtures/genome/*.vcf.gz.tbi
|
|
21
|
+
__pycache__/
|
|
22
|
+
*.pyc
|
|
23
|
+
.cache/
|
|
24
|
+
scholion-skill/
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Assistant rules
|
|
2
|
+
|
|
3
|
+
**This is the canonical file. It takes precedence over every other instruction.**
|
|
4
|
+
Rules change here and nowhere else. The "Core" block — universal rules, true for
|
|
5
|
+
any user — is copied by `src/tools/sync_rules.py` into **both** editions of the
|
|
6
|
+
skill. The "Owner's local notes" block goes **only** into the personal edition:
|
|
7
|
+
the particulars of one laboratory and one set of devices must not be shipped as
|
|
8
|
+
a general principle. Copies drifting from the canon are caught by
|
|
9
|
+
`run_tests.sh` and the `pre-push` hook; the personal block leaking into the
|
|
10
|
+
public edition is caught by `tests/test_skill_editions.py`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Core
|
|
15
|
+
|
|
16
|
+
<!-- CORE:BEGIN -->
|
|
17
|
+
**1. Role.** The assistant is a decision-support tool, not a physician. It does
|
|
18
|
+
not diagnose, does not start or stop therapy, does not adjust doses. The working
|
|
19
|
+
form is: "factor X is present and worth discussing with your physician before
|
|
20
|
+
prescribing Y". The decision always belongs to the treating physician.
|
|
21
|
+
|
|
22
|
+
**2. A source behind every statement.** Gene and rsID; a marker with its
|
|
23
|
+
collection date and units; the profile file; a PMID or a guideline with its
|
|
24
|
+
version. A number without an origin does not enter the profile and does not
|
|
25
|
+
appear in an answer.
|
|
26
|
+
|
|
27
|
+
**3. Annotation carries no direction.** "Pathogenic", `stop_gained`,
|
|
28
|
+
`frameshift`, a coloured mark in a commercial report — all of these describe the
|
|
29
|
+
variant's relation to the REFERENCE SEQUENCE, not to the person. What a mark
|
|
30
|
+
means in a particular report is read from that report's legend, not guessed from
|
|
31
|
+
its colour. Before any conclusion from the genome, five filters in order, and the
|
|
32
|
+
first one that fires closes the question: phenotype plausibility (before
|
|
33
|
+
consulting any database) → zygosity, inheritance mode and sex → allele direction
|
|
34
|
+
from a primary source → effect size against analytical error → coverage at that
|
|
35
|
+
exact position.
|
|
36
|
+
|
|
37
|
+
**4. A negative result is qualified by coverage.** "No findings" means "none in
|
|
38
|
+
the part that was read". Without per-gene callability the statement is empty: a
|
|
39
|
+
gene read at 70 % yields the same zero as a gene read at 100 %. Structural
|
|
40
|
+
variants are not called by short reads at all, so "a monogenic form is excluded"
|
|
41
|
+
cannot be said without a separate test.
|
|
42
|
+
|
|
43
|
+
**5. Absence of data is not a negative result.** "Not found in the profile" ≠
|
|
44
|
+
"was never tested"; "not in the archive" ≠ "was never done"; "the user remembers
|
|
45
|
+
it" ≠ "there is a form". Before any negative conclusion about labs, run
|
|
46
|
+
`selfcheck` / `reconcile`; call an unreadable file unreadable, not missing.
|
|
47
|
+
|
|
48
|
+
**6. Composite indices are computed from a single panel.** PhenoAge, HOMA-IR,
|
|
49
|
+
eGFR and ratios are computed from markers of one draw; substituting a missing
|
|
50
|
+
marker from an earlier panel is forbidden. A printed index from the same form
|
|
51
|
+
does not confirm a disputed value — it is the same number divided by a constant.
|
|
52
|
+
Confirmation requires a different draw or a different method.
|
|
53
|
+
|
|
54
|
+
**7. A reference interval is not an action threshold.** The interval comes from
|
|
55
|
+
the laboratory's form; the action threshold is derived from outcomes and may lie
|
|
56
|
+
inside the interval or far outside it. Three levels are named explicitly: outside
|
|
57
|
+
the interval, near the boundary relative to the person's own history, and a
|
|
58
|
+
crossed clinical threshold.
|
|
59
|
+
|
|
60
|
+
**8. What is probabilistic is called probabilistic.** A polygenic percentile
|
|
61
|
+
depends on the model, the reference population and which variants were actually
|
|
62
|
+
called; the model is pinned in a registry, and swapping it breaks the series and
|
|
63
|
+
requires an explicit note. A catalogue of published longevity associations is
|
|
64
|
+
navigation, not risk. A hypothesis is not presented as a fact.
|
|
65
|
+
|
|
66
|
+
**9. A threshold that fires on almost everything gets fixed, not explained.** A
|
|
67
|
+
cheap check before any interpretation: what fraction of objects did the flag hit?
|
|
68
|
+
If it hit almost all of them, it measures a property of the data rather than of
|
|
69
|
+
the objects. Any automatic exclusion leaves its reason next to the record:
|
|
70
|
+
something dropped silently is indistinguishable from something absent.
|
|
71
|
+
|
|
72
|
+
**10. Red flags are stated plainly.** Alarming values, dangerous drug
|
|
73
|
+
combinations, signs of serious conditions — name them directly and recommend an
|
|
74
|
+
in-person consultation rather than offering reassurance.
|
|
75
|
+
|
|
76
|
+
**11. Retracting a previous conclusion matters more than a new finding.** An old
|
|
77
|
+
formulation lives on in documents and in memory until it is explicitly withdrawn.
|
|
78
|
+
If a conclusion changed, say what exactly is retracted and why.
|
|
79
|
+
|
|
80
|
+
**12. An experiment is only as honest as its design allows.** The significance of
|
|
81
|
+
an n-of-1 trial is bounded by the number of blocks, not the number of days; that
|
|
82
|
+
bound is printed before the trial starts; a day the protocol was broken and the
|
|
83
|
+
day after it are excluded; a retrospective review generates hypotheses, it does
|
|
84
|
+
not test them.
|
|
85
|
+
|
|
86
|
+
**13. Privacy and standards.** The profile, the genome, laboratory values and
|
|
87
|
+
documents are never uploaded and are never part of a request: no analysis needs a
|
|
88
|
+
network. Two lookups do go out, only when the user asks for them by name, and each
|
|
89
|
+
sends the minimum query term to a named service — a drug name to RxNorm/RxClass
|
|
90
|
+
(and to a translator first if the name is Russian), an rsID to Ensembl, a gene or
|
|
91
|
+
drug identifier to CPIC. Say it that way rather than "nothing leaves the machine":
|
|
92
|
+
a drug name is itself a statement about the person asking, and a promise wider
|
|
93
|
+
than the truth is worth less than the narrower true one. Personal data does not go
|
|
94
|
+
into public repositories, issue trackers or third-party services. Standard codes
|
|
95
|
+
(LOINC, RxNorm, ATC) are never written from memory: an invented code looks like a
|
|
96
|
+
standard and silently breaks exchange — absent is better than wrong.
|
|
97
|
+
<!-- CORE:END -->
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Owner's local notes
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Why the rules are shaped this way
|
|
105
|
+
|
|
106
|
+
Each rule comes from a specific failure, not from general reasoning. What follows
|
|
107
|
+
is the class of failure behind each one — so that the next person editing this
|
|
108
|
+
file can see what must not be weakened. The particular measurements that produced
|
|
109
|
+
these lessons belong to one person's data and stay out of the public file; the
|
|
110
|
+
lesson is a class of problem, not an episode from someone's life.
|
|
111
|
+
|
|
112
|
+
**Rule 3** came from three independent cases in a single review. Most of a
|
|
113
|
+
pathogenic-tier list was dismissed by zygosity, inheritance mode and sex. Most of
|
|
114
|
+
the orange flags in a commercial report pointed in the favourable direction. And
|
|
115
|
+
a `frameshift` turned out to mean that a protein *appeared* rather than broke.
|
|
116
|
+
Three different ways for the same mistake: reading the relation to the reference
|
|
117
|
+
as a statement about the person.
|
|
118
|
+
|
|
119
|
+
**Rule 4** appeared once callability was actually measured. A typical clinical
|
|
120
|
+
gene is read well; some are not, and the difference changes what may be said to a
|
|
121
|
+
physician — "a monogenic form is not excluded" instead of "no pathogenic variants".
|
|
122
|
+
Genes with pseudogenes are not reliably closed by short reads at all. An average
|
|
123
|
+
across the genome gives no right to a claim about a specific gene.
|
|
124
|
+
|
|
125
|
+
**Rule 5** stands on four episodes with one shape. Markers missing from the
|
|
126
|
+
recognition dictionary made an audit report "no gaps", because it did not know
|
|
127
|
+
what to look for. Whole years of forms were discarded over a single date format.
|
|
128
|
+
An episode was first declared "never repeated" from the absence of a form, then
|
|
129
|
+
"closed" from memory — both wrong. Absence of evidence kept being read as
|
|
130
|
+
evidence of absence.
|
|
131
|
+
|
|
132
|
+
**Rule 6** came from a biological age computed with one input taken from a panel
|
|
133
|
+
two years older than the rest. The number looked convincing and meant nothing.
|
|
134
|
+
|
|
135
|
+
**Rule 7** came from two directions at once: a "near the boundary" zone wide
|
|
136
|
+
enough to fire on roughly every tenth marker of a healthy person, and a marker
|
|
137
|
+
whose laboratory flag and whose clinical action threshold sit far apart.
|
|
138
|
+
|
|
139
|
+
**Rule 8** came from double-counted positions in a re-genotyped VCF, from
|
|
140
|
+
percentiles withdrawn after an audit, and from several models of the same trait
|
|
141
|
+
disagreeing across nearly the whole range.
|
|
142
|
+
|
|
143
|
+
**Rule 9** came from the same defect firing three times: the "near the boundary"
|
|
144
|
+
zone, an absolute coverage threshold whose first version marked every gene as
|
|
145
|
+
weak because it measured the sequencing run rather than the genes, and an extreme
|
|
146
|
+
polygenic percentile.
|
|
147
|
+
|
|
148
|
+
**Rule 12** came from a property of the design that is usually left unsaid: a
|
|
149
|
+
classic four-block ABAB trial cannot reach p<0.05 at all — its floor is 0.167.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Where things live
|
|
154
|
+
|
|
155
|
+
| What | Where |
|
|
156
|
+
|---|---|
|
|
157
|
+
| Assistant rules (this file) | `ASSISTANT-RULES.md` — canonical, precedence over everything |
|
|
158
|
+
| Purpose and caveats for an outside reader | `DISCLAIMER.md` |
|
|
159
|
+
| Operating steps and tools | the skill, `SKILL.md` |
|
|
160
|
+
| Rules for contributors and evidence requirements | `CONTRIBUTING.md` |
|
|
161
|
+
| Rules for development sessions, what never enters the repository | `CLAUDE.md` |
|
|
162
|
+
| Licences and source attribution | `LICENSE`, `LICENSE-DATA`, `NOTICE`, `ATTRIBUTION.md` |
|
|
163
|
+
|
|
164
|
+
No personal contacts and no information about any individual are kept in this
|
|
165
|
+
file: it ships in the public package.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Attribution and third-party licenses
|
|
2
|
+
|
|
3
|
+
This file records where every non-original piece of data in this repository
|
|
4
|
+
comes from, under what licence, and what the licence requires of anyone who
|
|
5
|
+
redistributes it. It is part of the licence conditions, not documentation.
|
|
6
|
+
|
|
7
|
+
Two rules govern the whole repository:
|
|
8
|
+
|
|
9
|
+
1. **Nothing enters `knowledge/` without a source.** A file with no
|
|
10
|
+
`_meta.source` is a defect.
|
|
11
|
+
2. **Nothing enters the repository whose licence forbids commercial use,
|
|
12
|
+
modification, or redistribution.** The code is Apache-2.0 and the data is
|
|
13
|
+
CC BY 4.0; both permit commercial use, so anything more restrictive is
|
|
14
|
+
incompatible by construction and is fetched at run time instead.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Data included in this repository
|
|
19
|
+
|
|
20
|
+
### LongevityMap — Human Ageing Genomic Resources (HAGR)
|
|
21
|
+
|
|
22
|
+
* File: `src/scholion/knowledge/longevitymap.json` (2 859 variants, 162 genes)
|
|
23
|
+
* Source: https://genomics.senescence.info/longevity/
|
|
24
|
+
* Licence: **Creative Commons Attribution 3.0 Unported** — free for all
|
|
25
|
+
purposes including commercial, citation required
|
|
26
|
+
(https://genomics.senescence.info/legal.html)
|
|
27
|
+
* Required citation — HAGR asks for both the resource and the specific database.
|
|
28
|
+
Check the site for the currently preferred references before publication:
|
|
29
|
+
* Tacutu R, Thornton D, Johnson E, et al. *Human Ageing Genomic Resources:
|
|
30
|
+
new and updated databases.* Nucleic Acids Research, 2018.
|
|
31
|
+
* Budovsky A, Craig T, Wang J, et al. *LongevityMap: a database of human
|
|
32
|
+
genetic variants associated with longevity.* Trends in Genetics, 2013.
|
|
33
|
+
* Note: CC BY **3.0** does not expressly address the European sui generis
|
|
34
|
+
database right, unlike CC BY 4.0. For EU users this is a grey area inherited
|
|
35
|
+
from the upstream source, not something this project can resolve.
|
|
36
|
+
|
|
37
|
+
### Pharmacogenomic gene–drug reference
|
|
38
|
+
|
|
39
|
+
* File: `src/scholion/knowledge/cpic_drug_gene.json`
|
|
40
|
+
* Written by hand from the published principles of CPIC guidelines. **No CPIC
|
|
41
|
+
table is copied.** CPIC content is dedicated to the public domain under CC0
|
|
42
|
+
(https://www.clinpgx.org/page/dataUsagePolicy).
|
|
43
|
+
* The CPIC® name is a registered mark and the CPIC logo belongs to NIH; neither
|
|
44
|
+
is used in this project's branding or promotion.
|
|
45
|
+
* PharmGKB content is licensed CC BY-SA 4.0, whose ShareAlike term would
|
|
46
|
+
propagate to any derivative file. **No PharmGKB table is copied**, and no
|
|
47
|
+
file here is derived from one.
|
|
48
|
+
|
|
49
|
+
### LOINC — Regenstrief Institute
|
|
50
|
+
|
|
51
|
+
* File: `src/scholion/knowledge/lab_test_meta.json` (34 verified codes)
|
|
52
|
+
* Source: https://loinc.org — free of charge under the LOINC license
|
|
53
|
+
* Licence condition: redistribution requires the verbatim notice reproduced in
|
|
54
|
+
`NOTICE`. It is not optional and not paraphrasable; section 10(a) of the
|
|
55
|
+
licence fixes its wording.
|
|
56
|
+
* Each code is stored next to the test it identifies and its LOINC long common
|
|
57
|
+
name, as the licence requires. Codes that could not be verified against the
|
|
58
|
+
LOINC search service are marked `loinc_status` and left empty — an unverified
|
|
59
|
+
code is worse than none, because it silently maps a test to the wrong concept.
|
|
60
|
+
|
|
61
|
+
### PGS Catalog model registry
|
|
62
|
+
|
|
63
|
+
* File: `src/scholion/knowledge/prs_models.json`
|
|
64
|
+
* Contains **only public PGS identifiers** (e.g. `PGS000123`) and this project's
|
|
65
|
+
own notes about why a model was pinned. **No scoring weights are included.**
|
|
66
|
+
* This is a deliberate constraint: the PGS Catalog sets no single licence, each
|
|
67
|
+
scoring file carries its own, and some are CC BY-NC-ND — incompatible with
|
|
68
|
+
this repository. Weights are downloaded by the user from
|
|
69
|
+
https://www.pgscatalog.org/ under the terms of each individual score.
|
|
70
|
+
|
|
71
|
+
### Everything else in `knowledge/`
|
|
72
|
+
|
|
73
|
+
`acmg_sf.json`, `clinical_thresholds.json`, `dose_evidence.json`,
|
|
74
|
+
`drug_interactions.json`, `drug_lab_monitoring.json`, `lab_markers.json`,
|
|
75
|
+
`lab_test_meta.json`, `loci.json`, `longevity_directions.json`,
|
|
76
|
+
`med_classes.json`, `penetrance.json`, `prs_traits.json`, `test_rules.json`,
|
|
77
|
+
`experiment_templates.json`, `wearable_metrics.json` are original compilations
|
|
78
|
+
written for this project. Individual entries cite primary literature, clinical
|
|
79
|
+
guidelines and genome coordinates verified against Ensembl; citing a fact is
|
|
80
|
+
not redistributing a database. Where an entry reflects a specific guideline,
|
|
81
|
+
the guideline is named in the entry itself.
|
|
82
|
+
|
|
83
|
+
The ACMG Secondary Findings gene list reflects the recommendations of the
|
|
84
|
+
American College of Medical Genetics and Genomics (SF v3.3); the list of gene
|
|
85
|
+
symbols is factual, the reporting rules are implemented in this project's own
|
|
86
|
+
code.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Resources used at run time and NOT redistributed here
|
|
91
|
+
|
|
92
|
+
The user obtains each of these directly from its provider, under that
|
|
93
|
+
provider's terms. This project only calls them.
|
|
94
|
+
|
|
95
|
+
| Resource | Provider | Terms |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| ClinVar | NCBI / NLM | Redistribution permitted; attribution requested. NCBI asks that ClinVar data be accompanied by the note that it is *not intended for direct diagnostic use or medical decision-making without review by a genetics professional* — this project reproduces that position in DISCLAIMER.md. https://www.ncbi.nlm.nih.gov/clinvar/docs/maintenance_use/ |
|
|
98
|
+
| dbSNP | NCBI / NLM | rsIDs used as identifiers. NCBI policies apply. |
|
|
99
|
+
| Ensembl REST (incl. 1000 Genomes and gnomAD allele frequencies) | EMBL-EBI | Queried at run time for coordinates and population frequencies. EMBL-EBI terms of use; IGSR notes that rights vary between constituent datasets. |
|
|
100
|
+
| PGS Catalog scoring files | EMBL-EBI / PGS Catalog | Licence declared per score inside each file. |
|
|
101
|
+
| RxNorm and RxClass, including ATC codes | NLM | Queried at run time. **ATC codes are never stored in this repository:** the WHO Collaborating Centre prohibits copying and distribution for commercial purposes, which is incompatible with a permissively licensed repository. |
|
|
102
|
+
| SNOMED CT | SNOMED International | **Not used.** Requires an Affiliate licence; incompatible with open redistribution. |
|
|
103
|
+
| LOINC | Regenstrief Institute | **Used and redistributed** — see the dedicated section below. |
|
|
104
|
+
|
|
105
|
+
## External tools invoked, not bundled
|
|
106
|
+
|
|
107
|
+
Installed by the user; this project executes them and reads their output.
|
|
108
|
+
|
|
109
|
+
| Tool | Licence |
|
|
110
|
+
|---|---|
|
|
111
|
+
| PharmCAT | Mozilla Public License 2.0 |
|
|
112
|
+
| PyPGx | MIT |
|
|
113
|
+
| T1K | MIT |
|
|
114
|
+
| bcftools, samtools (HTSlib) | MIT/Expat |
|
|
115
|
+
| Ensembl VEP | Apache-2.0 |
|
|
116
|
+
| BWA | GPL-3.0 (invoked as a separate process; no code is linked or copied) |
|
|
117
|
+
| telomerecat | as published by its authors |
|
|
118
|
+
| DeepVariant | BSD-3-Clause |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Reporting a licensing problem
|
|
123
|
+
|
|
124
|
+
If you believe something here is misattributed or should not be redistributed,
|
|
125
|
+
open an issue titled `licensing:` or write to the maintainer. Data whose status
|
|
126
|
+
is unclear is removed first and discussed second.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Semantic versions with the date in the heading: `v0.2.0 — 20.08.2026`. The number
|
|
4
|
+
is the unique key of an entry, the date is informative: a working day may produce
|
|
5
|
+
several versions or none. Rules for choosing a number — `docs/VERSIONING.md`.
|
|
6
|
+
|
|
7
|
+
**The numbering starts here.** This journal opens at the first public release. The
|
|
8
|
+
development that produced it ran under its own numbering, up to `2.24.0`, and that
|
|
9
|
+
numbering was retired at publication: it measured how much had been built, and a
|
|
10
|
+
version number is meant to promise something else — that a person holding the
|
|
11
|
+
previous version knows what moving to this one does to their data and their
|
|
12
|
+
commands. Nobody outside had run any of those versions, so there was nothing to
|
|
13
|
+
promise. They are kept privately, in `CHANGELOG.pre-0.1.0.md`, and their tags live
|
|
14
|
+
in a namespace of their own (`pre-0.1.0/v2.24.0`), so that if the published
|
|
15
|
+
numbering ever reaches `2.24.0` it is a different tag on a different commit and
|
|
16
|
+
cannot be mistaken for one of them.
|
|
17
|
+
|
|
18
|
+
**How to read it.** The main sections of an entry are not the file list but three
|
|
19
|
+
curated ones: **what this changes in the conclusions**, **what is retracted**,
|
|
20
|
+
**what needs recomputing**. The file list at the bottom is generated from git
|
|
21
|
+
(`python3 src/tools/release_notes.py`). A **series break** is marked separately —
|
|
22
|
+
a change to `src/scholion/knowledge/` that alters the result on unchanged input.
|
|
23
|
+
Values from before and after such a change cannot go on the same chart without a
|
|
24
|
+
note.
|
|
25
|
+
|
|
26
|
+
**What is not here.** Personal data and one person's findings: no genotypes, no
|
|
27
|
+
lab values, no dates of anyone's tests. This journal records what changed in the
|
|
28
|
+
**system**, not what was found in somebody.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
<!-- NEW ENTRIES GO HERE -->
|
|
33
|
+
|
|
34
|
+
## v0.1.2 — 17.08.2026
|
|
35
|
+
|
|
36
|
+
_Comparison base: v0.1.1 → the working tree (not committed yet). Commits: 0. 5 files changed, 79 insertions(+), 13 deletions(-)._
|
|
37
|
+
|
|
38
|
+
### What this changes in the conclusions
|
|
39
|
+
|
|
40
|
+
Nothing about anyone's health, and nothing in how a result is computed.
|
|
41
|
+
`set-folder` used to accept only a fixed list of eight domain names (labs,
|
|
42
|
+
medications, metrics, genome, labs_docs, med_docs, garmin, apple_health — the
|
|
43
|
+
last one newly recognised in this release, though nothing parses it yet) and
|
|
44
|
+
refused everything else outright. A source folder that is legitimately
|
|
45
|
+
personal — a CGM app's screenshots, a specific sequencing provider's export
|
|
46
|
+
folder, whatever the next such folder turns out to be called — had no way to
|
|
47
|
+
be recorded at all.
|
|
48
|
+
|
|
49
|
+
An unrecognised domain name is now accepted rather than refused, and filed
|
|
50
|
+
under a new `external_sources` section of `profile/sources.json` instead of
|
|
51
|
+
`folders`. `core.source_config()` — what every reader of a configured folder
|
|
52
|
+
actually calls — merges both sections, so the split matters only at the
|
|
53
|
+
moment a folder is set, never when one is read back.
|
|
54
|
+
|
|
55
|
+
The trade-off is explicit, not accidental: the old refusal also caught a typo
|
|
56
|
+
of one of the eight names as a side effect ("grmin" for "garmin"). Opening the
|
|
57
|
+
domain up removes that — a near-miss is now just an ordinary new
|
|
58
|
+
`external_sources` entry, and the intended domain is left untouched, not
|
|
59
|
+
corrected. Nothing reads `external_sources` programmatically yet, so today
|
|
60
|
+
that costs nothing silent.
|
|
61
|
+
|
|
62
|
+
### What is withdrawn
|
|
63
|
+
|
|
64
|
+
Nothing.
|
|
65
|
+
|
|
66
|
+
### What needs recomputing
|
|
67
|
+
|
|
68
|
+
Nothing. No stored value, no catalogue and no conclusion changed.
|
|
69
|
+
|
|
70
|
+
### Changes by file
|
|
71
|
+
|
|
72
|
+
**Engine and application**
|
|
73
|
+
|
|
74
|
+
- `src/scholion/cli.py` — changed
|
|
75
|
+
- `src/scholion/core.py` — changed
|
|
76
|
+
- `src/scholion/store.py` — changed
|
|
77
|
+
|
|
78
|
+
**Tests**
|
|
79
|
+
|
|
80
|
+
- `tests/test_external_sources.py` — added
|
|
81
|
+
|
|
82
|
+
**Other**
|
|
83
|
+
|
|
84
|
+
- `VERSION` — changed
|
|
85
|
+
|
|
86
|
+
## v0.1.1 — 16.08.2026
|
|
87
|
+
|
|
88
|
+
_Comparison base: v0.1.0 → the working tree (not committed yet). Commits: 0. 1 file changed, 53 insertions(+), 1 deletion(-)._
|
|
89
|
+
|
|
90
|
+
### What this changes in the conclusions
|
|
91
|
+
|
|
92
|
+
Nothing about anyone's health. Two defects in the gate that runs last — the
|
|
93
|
+
pre-push hook — one of which would have stopped the first push of this repository
|
|
94
|
+
anywhere.
|
|
95
|
+
|
|
96
|
+
**The pre-push check refused the synthetic genome fixture.** `tests/fixtures/genome/
|
|
97
|
+
tiny.vcf.gz` is the one genome file this project allows into its history, and it is
|
|
98
|
+
allowed by content rather than by name: the header has to declare it invented, and
|
|
99
|
+
the call set has to be small enough that nothing real fits through. Four gates ask
|
|
100
|
+
`synthetic_fixture` that question — the pre-commit hook, the build audit, the
|
|
101
|
+
repository-hygiene test, the `.gitignore` negation. `check_push.py` never did. It
|
|
102
|
+
saw a `.vcf.gz` in the history and blocked, which means every earlier gate could
|
|
103
|
+
approve the repository and the last one would refuse it at the moment of pushing,
|
|
104
|
+
over a file the project ships deliberately. The exception is now asked of the same
|
|
105
|
+
module the other four ask, so it cannot drift between them.
|
|
106
|
+
|
|
107
|
+
**The pre-publication tags could travel out with `git push --tags`.** 32 tags named
|
|
108
|
+
`v1.0.0` … `v2.24.0` live under `pre-0.1.0/` because the numbering was reset at
|
|
109
|
+
publication and those same numbers will be used again. `git push --tags` does not
|
|
110
|
+
ask which tags — it sends every tag it has. The CI filter (`tags: ["v*"]`) would
|
|
111
|
+
not have published them to PyPI, but by then they would already be in a public
|
|
112
|
+
history, and a pushed tag is not taken back by deleting it locally. The hook is the
|
|
113
|
+
only place that sees the refs and can still say no; it now refuses them by name and
|
|
114
|
+
prints what to push instead.
|
|
115
|
+
|
|
116
|
+
Neither would have fired today — the private repository has no remote, so there is
|
|
117
|
+
nowhere to push. Both would have fired the first time one was added.
|
|
118
|
+
|
|
119
|
+
### What is retracted
|
|
120
|
+
|
|
121
|
+
Nothing published. The claim being corrected is internal: that the five gates
|
|
122
|
+
guarding personal data all asked one predicate. Four did.
|
|
123
|
+
|
|
124
|
+
### What needs recomputing
|
|
125
|
+
|
|
126
|
+
Nothing. No stored value, no catalogue and no conclusion changed.
|
|
127
|
+
|
|
128
|
+
### Changes by file
|
|
129
|
+
|
|
130
|
+
**Tools and build**
|
|
131
|
+
|
|
132
|
+
- `src/tools/check_push.py` — changed
|
|
133
|
+
|
|
134
|
+
## v0.1.0 — 16.08.2026
|
|
135
|
+
|
|
136
|
+
_The first release anyone outside the project can install._
|
|
137
|
+
|
|
138
|
+
### What this changes in the conclusions
|
|
139
|
+
|
|
140
|
+
Nothing is retracted and nothing needs recomputing: there is no previous public
|
|
141
|
+
version to compare against. What follows is what the release contains and, more
|
|
142
|
+
importantly, what its number means.
|
|
143
|
+
|
|
144
|
+
### What the number means
|
|
145
|
+
|
|
146
|
+
**Below `1.0.0` the public contract may break.** Command names, the top-level
|
|
147
|
+
fields of `--json`, the file names inside a profile — the project's own rule is
|
|
148
|
+
that these may grow and may not shrink, and `python3 src/tools/check_compat.py`
|
|
149
|
+
enforces it on every run. Until `1.0.0` that rule is **internal discipline, not a
|
|
150
|
+
promise made to anyone outside**: it is stated here so that a person who builds on
|
|
151
|
+
`--json` knows precisely how much weight it carries, which is some, and not all.
|
|
152
|
+
|
|
153
|
+
**`1.0.0` arrives by use, not by features.** The condition is a number of people
|
|
154
|
+
who have run this on their own medical data and said what happened — not a count
|
|
155
|
+
of finished capabilities. Everything in this release was verified on invented
|
|
156
|
+
forms, an invented profile and one real record; the failure modes that matter for
|
|
157
|
+
a system like this appear in the second record and in the tenth, not in the first,
|
|
158
|
+
and no amount of building substitutes for that.
|
|
159
|
+
|
|
160
|
+
### What it does
|
|
161
|
+
|
|
162
|
+
Reads a person's genome, laboratory history, prescriptions, clinical conclusions
|
|
163
|
+
and wearable data against each other, locally, with the source shown behind every
|
|
164
|
+
statement. One core with three entry points — a local web app, a command line, and
|
|
165
|
+
a skill for a language model — and a rule, enforced by a test, that a capability
|
|
166
|
+
appears in all of them at once.
|
|
167
|
+
|
|
168
|
+
The part worth naming is what it refuses to do:
|
|
169
|
+
|
|
170
|
+
- **A value without a reference corridor is never shown as normal.** Green means
|
|
171
|
+
«inside the corridor»; with no corridor there is no such claim to make.
|
|
172
|
+
- **A connected genome cannot make an answer less cautious.** A position with no
|
|
173
|
+
row in a VCF is either the reference or no coverage at all, and the file does
|
|
174
|
+
not say which — so it is carried as an explicit confidence level rather than
|
|
175
|
+
collapsed into «reference». Before this was fixed, a person with a genome
|
|
176
|
+
attached could get a calmer answer about a drug than the same person without one.
|
|
177
|
+
- **Units are a gate before they are a conversion table.** A value is admitted into
|
|
178
|
+
a series only in a unit the marker declares, and the reference range is converted
|
|
179
|
+
with it — the two travelling apart is a defect this project found in itself.
|
|
180
|
+
- **A source that was never reached makes no negative statement.** «No significant
|
|
181
|
+
pharmacogenetics» and «the database did not answer» are different sentences.
|
|
182
|
+
- **What is not known is printed.** `scholion limits` states the coverage behind
|
|
183
|
+
the genomic conclusions and names what cannot be concluded from the data present.
|
|
184
|
+
|
|
185
|
+
Everything it produces is material for a person's own decisions and for a
|
|
186
|
+
conversation with their physician. It is not a medical device, it is not a
|
|
187
|
+
clinical decision support system, and it does not diagnose.
|
|
188
|
+
|
|
189
|
+
### What is knowingly incomplete
|
|
190
|
+
|
|
191
|
+
- **Nobody outside has run this yet.** That is the single largest gap in the
|
|
192
|
+
evidence behind everything above.
|
|
193
|
+
- **eGFR is not read from an English laboratory form.** Its value is printed on the
|
|
194
|
+
line below its name, and relaxing that rule would take a wrong number on the very
|
|
195
|
+
form the rule was written for. It needs a real English form to decide on, and
|
|
196
|
+
there is not one — so it stays named rather than fitted.
|
|
197
|
+
- **175 markers are recognised in Russian only** — urine organic acids, the
|
|
198
|
+
coprogram, the dysbacteriosis culture, the element panels. They are barely
|
|
199
|
+
ordered outside Russia; their labels are work an outside contributor can do
|
|
200
|
+
without touching any logic.
|
|
201
|
+
- **LOINC codes are absent.** The table is available from Regenstrief, and using it
|
|
202
|
+
obliges the project to ship a verbatim notice in `NOTICE` in the same commit.
|
|
203
|
+
Neither half could be done honestly on release day.
|
|
204
|
+
- **Pharmacogenetics covers seven genes** — the core with the strongest evidence,
|
|
205
|
+
not a full panel. CYP2D6 as a whole needs a dedicated tool: structural variants
|
|
206
|
+
and phasing.
|
|
207
|
+
|
|
208
|
+
### What holds it together
|
|
209
|
+
|
|
210
|
+
393 tests, run offline against synthetic fixtures and executed inside the built
|
|
211
|
+
package rather than only in the repository. A parsing baseline recorded *before*
|
|
212
|
+
the dictionary migration that followed it — the timing is the value: a baseline
|
|
213
|
+
recorded after a change states that the code equals itself and passes on any
|
|
214
|
+
behaviour. Every test written for a defect was re-run against the un-fixed code to
|
|
215
|
+
prove it catches it. A build audit that fails the package on any personal datum —
|
|
216
|
+
in plain text or encoded — and three independent barriers keeping personal data
|
|
217
|
+
out of git.
|
|
218
|
+
|
|
219
|
+
---
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Citation File Format 1.2.0 — https://citation-file-format.github.io
|
|
2
|
+
#
|
|
3
|
+
# Checked by a test alongside the other legal files: the version number here is
|
|
4
|
+
# obliged to match the VERSION file. There is one source of truth — VERSION; this
|
|
5
|
+
# field is only a copy of it, and the test exists precisely so that the copy does
|
|
6
|
+
# not drift.
|
|
7
|
+
#
|
|
8
|
+
# An ORCID goes here once there is one and it is meant for public use:
|
|
9
|
+
# orcid: "https://orcid.org/0000-0000-0000-0000"
|
|
10
|
+
cff-version: 1.2.0
|
|
11
|
+
message: "If you use Scholion in research, please cite it using this metadata."
|
|
12
|
+
title: "Scholion"
|
|
13
|
+
version: "0.1.2"
|
|
14
|
+
date-released: "2026-08-17"
|
|
15
|
+
type: software
|
|
16
|
+
authors:
|
|
17
|
+
- family-names: "Belevtsev"
|
|
18
|
+
given-names: "Andrey"
|
|
19
|
+
repository-code: "https://github.com/CrossRead/scholion"
|
|
20
|
+
url: "https://github.com/CrossRead/scholion"
|
|
21
|
+
license: "Apache-2.0"
|
|
22
|
+
keywords:
|
|
23
|
+
- personal health data
|
|
24
|
+
- genomics
|
|
25
|
+
- pharmacogenomics
|
|
26
|
+
- polygenic scores
|
|
27
|
+
- laboratory results
|
|
28
|
+
- wearables
|
|
29
|
+
- n-of-1
|
|
30
|
+
- local-first
|
|
31
|
+
- provenance
|
|
32
|
+
abstract: >-
|
|
33
|
+
A local-first personal evidence workspace that connects laboratory results,
|
|
34
|
+
medications, wearable data, clinical documents and personal genomics, keeping
|
|
35
|
+
the source, date, units, coverage and interpretation limits attached to every
|
|
36
|
+
statement it makes. Intended for personal research and for discussion with a
|
|
37
|
+
clinician. It is not a diagnostic device and does not prescribe treatment.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Contributing to Scholion
|
|
2
|
+
|
|
3
|
+
Two things make this project useful: an engine that refuses to overstate what
|
|
4
|
+
it knows, and a knowledge base that is right. You can improve the second
|
|
5
|
+
without touching the first, and that is the contribution we most need.
|
|
6
|
+
|
|
7
|
+
_This is the short version, sufficient for a first pull request. It will be
|
|
8
|
+
expanded before the public launch._
|
|
9
|
+
|
|
10
|
+
## The shape of a contribution
|
|
11
|
+
|
|
12
|
+
The engine and the knowledge are deliberately separate. To teach the system a
|
|
13
|
+
new drug, marker, interaction, monitoring rule or clinical threshold you do
|
|
14
|
+
**not** need to read `engine.py` or `core.py` — you add entries to the JSON
|
|
15
|
+
files in `src/scholion/knowledge/`.
|
|
16
|
+
|
|
17
|
+
## Evidence rules for `knowledge/`
|
|
18
|
+
|
|
19
|
+
A pull request that adds or changes a clinical statement is merged only if the
|
|
20
|
+
entry carries, in the entry itself:
|
|
21
|
+
|
|
22
|
+
1. **A source.** A peer-reviewed publication (PMID or DOI) or a named clinical
|
|
23
|
+
guideline with its version — CPIC, DPWG, ADA, ESC, KDIGO, ACMG and the like.
|
|
24
|
+
"Commonly known", a blog, a supplement vendor and a language model are not
|
|
25
|
+
sources.
|
|
26
|
+
2. **A population.** In whom was this established. A threshold derived in one
|
|
27
|
+
population is not a universal constant.
|
|
28
|
+
3. **A direction and an action.** What the finding means and what one is
|
|
29
|
+
supposed to do with it — including "nothing, this is navigational".
|
|
30
|
+
4. **Units and material** for anything laboratory-related, taken from a printed
|
|
31
|
+
report rather than from memory.
|
|
32
|
+
|
|
33
|
+
Standard identifiers — RxNorm RXCUI, ATC, LOINC — are welcome where you have
|
|
34
|
+
them from an official table. Do not write a code from memory: an invented
|
|
35
|
+
identifier looks like a standard and silently corrupts exchange. Absent is
|
|
36
|
+
better than wrong.
|
|
37
|
+
|
|
38
|
+
Where a contribution retracts an earlier statement, say so explicitly. In this
|
|
39
|
+
project a retraction is worth more than a new finding, because the old wording
|
|
40
|
+
lives on in documents and in people's heads until it is withdrawn.
|
|
41
|
+
|
|
42
|
+
## What must never enter this repository
|
|
43
|
+
|
|
44
|
+
* **Personal data of any kind** — your genome, your VCF, your laboratory
|
|
45
|
+
reports, your prescriptions, your wearable exports, screenshots of your
|
|
46
|
+
profile. Not in commits, not in issues, not in pull request comments. If you
|
|
47
|
+
need to demonstrate a bug, use the synthetic demo profile.
|
|
48
|
+
* **PGS scoring weights** — licence varies per score, some forbid commercial
|
|
49
|
+
use.
|
|
50
|
+
* **ATC code tables** — the WHO Collaborating Centre forbids commercial
|
|
51
|
+
redistribution. The software fetches them at run time instead.
|
|
52
|
+
* **SNOMED CT content** — requires an Affiliate licence.
|
|
53
|
+
* Any data whose licence forbids commercial use, modification, or
|
|
54
|
+
redistribution. See ATTRIBUTION.md.
|
|
55
|
+
|
|
56
|
+
## Sign your work — Developer Certificate of Origin
|
|
57
|
+
|
|
58
|
+
This project uses the DCO rather than a contributor licence agreement. You keep
|
|
59
|
+
your copyright; you certify that you have the right to submit what you submit.
|
|
60
|
+
|
|
61
|
+
Add a sign-off line to each commit:
|
|
62
|
+
|
|
63
|
+
git commit -s -m "knowledge: add ABCG2 monitoring rule"
|
|
64
|
+
|
|
65
|
+
which appends:
|
|
66
|
+
|
|
67
|
+
Signed-off-by: Your Name <your.email@example.com>
|
|
68
|
+
|
|
69
|
+
By doing so you certify the Developer Certificate of Origin 1.1
|
|
70
|
+
(https://developercertificate.org/).
|
|
71
|
+
|
|
72
|
+
## Licence of contributions
|
|
73
|
+
|
|
74
|
+
* Code contributions are licensed under the Apache License 2.0 (LICENSE).
|
|
75
|
+
* Contributions to `src/scholion/knowledge/` are licensed under
|
|
76
|
+
CC BY 4.0 (LICENSE-DATA).
|
|
77
|
+
|
|
78
|
+
## Before you open a pull request
|
|
79
|
+
|
|
80
|
+
* `python3 -m compileall src` passes.
|
|
81
|
+
* Every JSON file you touched still parses.
|
|
82
|
+
* The engine runs against the synthetic demo profile without errors.
|
|
83
|
+
* You have not added a dependency. The engine is standard library only, and
|
|
84
|
+
that is a feature, not an oversight.
|
|
85
|
+
|
|
86
|
+
## Scope
|
|
87
|
+
|
|
88
|
+
Scholion is a research and educational tool, not a medical device — see
|
|
89
|
+
DISCLAIMER.md. Contributions that turn output into individualised medical
|
|
90
|
+
advice, prescriptions or dose selection are out of scope regardless of how well
|
|
91
|
+
they are evidenced.
|