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.
Files changed (210) hide show
  1. scholion-0.1.2/.gitignore +24 -0
  2. scholion-0.1.2/ASSISTANT-RULES.md +165 -0
  3. scholion-0.1.2/ATTRIBUTION.md +126 -0
  4. scholion-0.1.2/CHANGELOG.md +219 -0
  5. scholion-0.1.2/CITATION.cff +37 -0
  6. scholion-0.1.2/CONTRIBUTING.md +91 -0
  7. scholion-0.1.2/DISCLAIMER.md +74 -0
  8. scholion-0.1.2/LICENSE +202 -0
  9. scholion-0.1.2/LICENSE-DATA +55 -0
  10. scholion-0.1.2/NOTICE +65 -0
  11. scholion-0.1.2/PKG-INFO +542 -0
  12. scholion-0.1.2/README.md +501 -0
  13. scholion-0.1.2/SECURITY.md +124 -0
  14. scholion-0.1.2/THREAT_MODEL.md +120 -0
  15. scholion-0.1.2/VERSION +1 -0
  16. scholion-0.1.2/pyproject.toml +141 -0
  17. scholion-0.1.2/run_tests.sh +56 -0
  18. scholion-0.1.2/src/ingest/.gitkeep +0 -0
  19. scholion-0.1.2/src/ingest/README_track2.md +59 -0
  20. scholion-0.1.2/src/ingest/_sample.py +20 -0
  21. scholion-0.1.2/src/ingest/_sample.sh +19 -0
  22. scholion-0.1.2/src/ingest/acmg_sf_scan.py +201 -0
  23. scholion-0.1.2/src/ingest/ancestry_check.py +175 -0
  24. scholion-0.1.2/src/ingest/annotate_clinvar.sh +118 -0
  25. scholion-0.1.2/src/ingest/auto_full_vcf.sh +75 -0
  26. scholion-0.1.2/src/ingest/build_clinical_bed.py +103 -0
  27. scholion-0.1.2/src/ingest/build_longevity_sites.py +104 -0
  28. scholion-0.1.2/src/ingest/build_longevitymap.py +159 -0
  29. scholion-0.1.2/src/ingest/call_full_vcf.sh +91 -0
  30. scholion-0.1.2/src/ingest/clinvar_diff.py +100 -0
  31. scholion-0.1.2/src/ingest/csq_lof_scan.sh +270 -0
  32. scholion-0.1.2/src/ingest/deepvariant_call.sh +83 -0
  33. scholion-0.1.2/src/ingest/draw_checklist.py +434 -0
  34. scholion-0.1.2/src/ingest/extract_pgx_loci.sh +89 -0
  35. scholion-0.1.2/src/ingest/fastq_to_vcf.sh +143 -0
  36. scholion-0.1.2/src/ingest/first_run_check.py +213 -0
  37. scholion-0.1.2/src/ingest/hla_typing.sh +134 -0
  38. scholion-0.1.2/src/ingest/ingest_garmin.py +302 -0
  39. scholion-0.1.2/src/ingest/loci_sites_bed.py +55 -0
  40. scholion-0.1.2/src/ingest/longevity_findings_build.py +271 -0
  41. scholion-0.1.2/src/ingest/longevity_report.py +205 -0
  42. scholion-0.1.2/src/ingest/mtdna_haplogroup.sh +116 -0
  43. scholion-0.1.2/src/ingest/nof1.py +528 -0
  44. scholion-0.1.2/src/ingest/parse_evogen_pdf.py +161 -0
  45. scholion-0.1.2/src/ingest/parse_health_export.py +129 -0
  46. scholion-0.1.2/src/ingest/pgx_star_alleles.sh +137 -0
  47. scholion-0.1.2/src/ingest/pharmcat_run.sh +78 -0
  48. scholion-0.1.2/src/ingest/phenoage.py +44 -0
  49. scholion-0.1.2/src/ingest/prs_ancestry_sensitivity.py +153 -0
  50. scholion-0.1.2/src/ingest/prs_diff.py +107 -0
  51. scholion-0.1.2/src/ingest/prs_extract_models.py +107 -0
  52. scholion-0.1.2/src/ingest/prs_extract_sites.py +107 -0
  53. scholion-0.1.2/src/ingest/prs_genotype_sites.sh +44 -0
  54. scholion-0.1.2/src/ingest/prs_model_review.py +83 -0
  55. scholion-0.1.2/src/ingest/prs_results_build.py +225 -0
  56. scholion-0.1.2/src/ingest/prs_top_audit.py +103 -0
  57. scholion-0.1.2/src/ingest/prs_verify.py +467 -0
  58. scholion-0.1.2/src/ingest/qc_callability.sh +288 -0
  59. scholion-0.1.2/src/ingest/qc_tstv.sh +22 -0
  60. scholion-0.1.2/src/ingest/quarterly_reanalysis.sh +143 -0
  61. scholion-0.1.2/src/ingest/recheck_from_bam.sh +21 -0
  62. scholion-0.1.2/src/ingest/resume_merge_call.sh +46 -0
  63. scholion-0.1.2/src/ingest/setup_just_prs.sh +45 -0
  64. scholion-0.1.2/src/ingest/sle_p100_debug.py +149 -0
  65. scholion-0.1.2/src/ingest/telomere_length.py +122 -0
  66. scholion-0.1.2/src/ingest/update_catalog.py +91 -0
  67. scholion-0.1.2/src/ingest/update_check.sh +34 -0
  68. scholion-0.1.2/src/ingest/vcf_concordance.py +138 -0
  69. scholion-0.1.2/src/ingest/vcf_dedup_positions.py +18 -0
  70. scholion-0.1.2/src/ingest/vep_lof_scan.sh +218 -0
  71. scholion-0.1.2/src/ingest/verify_evogen.py +196 -0
  72. scholion-0.1.2/src/scholion/__init__.py +28 -0
  73. scholion-0.1.2/src/scholion/__main__.py +5 -0
  74. scholion-0.1.2/src/scholion/assistant.py +431 -0
  75. scholion-0.1.2/src/scholion/cli.py +537 -0
  76. scholion-0.1.2/src/scholion/contract.py +181 -0
  77. scholion-0.1.2/src/scholion/core.py +1098 -0
  78. scholion-0.1.2/src/scholion/demo.py +711 -0
  79. scholion-0.1.2/src/scholion/drugsource.py +284 -0
  80. scholion-0.1.2/src/scholion/engine.py +2299 -0
  81. scholion-0.1.2/src/scholion/format.py +1082 -0
  82. scholion-0.1.2/src/scholion/garmin.py +174 -0
  83. scholion-0.1.2/src/scholion/genome.py +481 -0
  84. scholion-0.1.2/src/scholion/i18n/__init__.py +140 -0
  85. scholion-0.1.2/src/scholion/i18n/en.py +1801 -0
  86. scholion-0.1.2/src/scholion/i18n/ru.py +1708 -0
  87. scholion-0.1.2/src/scholion/import_csv.py +161 -0
  88. scholion-0.1.2/src/scholion/ingest_labs.py +911 -0
  89. scholion-0.1.2/src/scholion/ingest_studies.py +195 -0
  90. scholion-0.1.2/src/scholion/knowledge/acmg_sf.json +1035 -0
  91. scholion-0.1.2/src/scholion/knowledge/clinical_thresholds.json +193 -0
  92. scholion-0.1.2/src/scholion/knowledge/cpic_drug_gene.json +946 -0
  93. scholion-0.1.2/src/scholion/knowledge/dose_evidence.json +550 -0
  94. scholion-0.1.2/src/scholion/knowledge/drug_interactions.json +442 -0
  95. scholion-0.1.2/src/scholion/knowledge/drug_lab_monitoring.json +245 -0
  96. scholion-0.1.2/src/scholion/knowledge/experiment_templates.json +73 -0
  97. scholion-0.1.2/src/scholion/knowledge/external_tools.json +295 -0
  98. scholion-0.1.2/src/scholion/knowledge/lab_markers.json +9099 -0
  99. scholion-0.1.2/src/scholion/knowledge/lab_test_meta.json +370 -0
  100. scholion-0.1.2/src/scholion/knowledge/loci.json +387 -0
  101. scholion-0.1.2/src/scholion/knowledge/longevity_directions.json +316 -0
  102. scholion-0.1.2/src/scholion/knowledge/longevitymap.json +40795 -0
  103. scholion-0.1.2/src/scholion/knowledge/med_classes.json +640 -0
  104. scholion-0.1.2/src/scholion/knowledge/penetrance.json +189 -0
  105. scholion-0.1.2/src/scholion/knowledge/prs_models.json +508 -0
  106. scholion-0.1.2/src/scholion/knowledge/prs_traits.json +982 -0
  107. scholion-0.1.2/src/scholion/knowledge/test_rules.json +220 -0
  108. scholion-0.1.2/src/scholion/knowledge/units.json +232 -0
  109. scholion-0.1.2/src/scholion/knowledge/wearable_metrics.json +355 -0
  110. scholion-0.1.2/src/scholion/limits.py +288 -0
  111. scholion-0.1.2/src/scholion/net.py +145 -0
  112. scholion-0.1.2/src/scholion/ouroboros_tools.py +163 -0
  113. scholion-0.1.2/src/scholion/phenoage.py +204 -0
  114. scholion-0.1.2/src/scholion/provenance.py +207 -0
  115. scholion-0.1.2/src/scholion/prs.py +359 -0
  116. scholion-0.1.2/src/scholion/reconcile.py +319 -0
  117. scholion-0.1.2/src/scholion/redact.py +143 -0
  118. scholion-0.1.2/src/scholion/server.py +470 -0
  119. scholion-0.1.2/src/scholion/skill/ASSISTANT-RULES.md +165 -0
  120. scholion-0.1.2/src/scholion/skill/SKILL.md +1105 -0
  121. scholion-0.1.2/src/scholion/store.py +455 -0
  122. scholion-0.1.2/src/scholion/tabixlite.py +127 -0
  123. scholion-0.1.2/src/scholion/templates/genome/README.md +41 -0
  124. scholion-0.1.2/src/scholion/templates/panel-template.csv +23 -0
  125. scholion-0.1.2/src/scholion/templates/profile/experiments.json +9 -0
  126. scholion-0.1.2/src/scholion/templates/profile/health_goals.json +24 -0
  127. scholion-0.1.2/src/scholion/templates/profile/index.md +14 -0
  128. scholion-0.1.2/src/scholion/templates/profile/labs.json +13 -0
  129. scholion-0.1.2/src/scholion/templates/profile/medications.json +10 -0
  130. scholion-0.1.2/src/scholion/templates/profile/metrics.json +11 -0
  131. scholion-0.1.2/src/scholion/templates/profile/pharmacogenomics.json +9 -0
  132. scholion-0.1.2/src/scholion/tools.py +498 -0
  133. scholion-0.1.2/src/scholion/web/apple-touch-icon.png +0 -0
  134. scholion-0.1.2/src/scholion/web/chart.min.js +14 -0
  135. scholion-0.1.2/src/scholion/web/dna.svg +16 -0
  136. scholion-0.1.2/src/scholion/web/favicon-16.png +0 -0
  137. scholion-0.1.2/src/scholion/web/favicon-32.png +0 -0
  138. scholion-0.1.2/src/scholion/web/favicon.ico +0 -0
  139. scholion-0.1.2/src/scholion/web/favicon.png +0 -0
  140. scholion-0.1.2/src/scholion/web/icon.svg +21 -0
  141. scholion-0.1.2/src/scholion/web/index.html +1625 -0
  142. scholion-0.1.2/src/tools/brief_edit.py +183 -0
  143. scholion-0.1.2/src/tools/check_compat.py +162 -0
  144. scholion-0.1.2/src/tools/check_language.py +380 -0
  145. scholion-0.1.2/src/tools/check_staged.py +299 -0
  146. scholion-0.1.2/src/tools/language_baseline.json +56 -0
  147. scholion-0.1.2/src/tools/make_demo_profile.py +20 -0
  148. scholion-0.1.2/src/tools/make_shareable.py +1222 -0
  149. scholion-0.1.2/src/tools/nof1_quick_log.sh +58 -0
  150. scholion-0.1.2/src/tools/sync_rules.py +200 -0
  151. scholion-0.1.2/src/tools/synthetic_fixture.py +130 -0
  152. scholion-0.1.2/tests/.gitkeep +0 -0
  153. scholion-0.1.2/tests/README.md +27 -0
  154. scholion-0.1.2/tests/__init__.py +0 -0
  155. scholion-0.1.2/tests/contracts/public_contract.json +222 -0
  156. scholion-0.1.2/tests/fixtures/genome/tiny.vcf.gz +0 -0
  157. scholion-0.1.2/tests/fixtures/genome/tiny.vcf.gz.tbi +0 -0
  158. scholion-0.1.2/tests/fixtures/labforms/01_biochem.txt +21 -0
  159. scholion-0.1.2/tests/fixtures/labforms/02_cbc.txt +14 -0
  160. scholion-0.1.2/tests/fixtures/labforms/03_hormones.txt +12 -0
  161. scholion-0.1.2/tests/fixtures/labforms/04_coprogram.txt +22 -0
  162. scholion-0.1.2/tests/fixtures/labforms/05_dysbiosis.txt +16 -0
  163. scholion-0.1.2/tests/fixtures/labforms/06_english_panel.txt +30 -0
  164. scholion-0.1.2/tests/fixtures/labforms/expected.json +201 -0
  165. scholion-0.1.2/tests/fixtures/profile/experiments.json +9 -0
  166. scholion-0.1.2/tests/fixtures/profile/health_goals.json +8 -0
  167. scholion-0.1.2/tests/fixtures/profile/index.md +14 -0
  168. scholion-0.1.2/tests/fixtures/profile/labs.json +32 -0
  169. scholion-0.1.2/tests/fixtures/profile/medications.json +7 -0
  170. scholion-0.1.2/tests/fixtures/profile/metrics.json +8 -0
  171. scholion-0.1.2/tests/fixtures/profile/pharmacogenomics.json +9 -0
  172. scholion-0.1.2/tests/support.py +109 -0
  173. scholion-0.1.2/tests/test_answerability.py +645 -0
  174. scholion-0.1.2/tests/test_atomic_write.py +68 -0
  175. scholion-0.1.2/tests/test_build_audit.py +704 -0
  176. scholion-0.1.2/tests/test_catalogue_integrity.py +236 -0
  177. scholion-0.1.2/tests/test_cli_smoke.py +145 -0
  178. scholion-0.1.2/tests/test_compat.py +44 -0
  179. scholion-0.1.2/tests/test_demo_drift.py +67 -0
  180. scholion-0.1.2/tests/test_demo_profile.py +85 -0
  181. scholion-0.1.2/tests/test_external_sources.py +170 -0
  182. scholion-0.1.2/tests/test_external_tools.py +326 -0
  183. scholion-0.1.2/tests/test_genome_fixture_gate.py +245 -0
  184. scholion-0.1.2/tests/test_genome_render.py +104 -0
  185. scholion-0.1.2/tests/test_i18n.py +149 -0
  186. scholion-0.1.2/tests/test_lab_dir_boundary.py +332 -0
  187. scholion-0.1.2/tests/test_lab_parsing_baseline.py +172 -0
  188. scholion-0.1.2/tests/test_language_baseline.py +76 -0
  189. scholion-0.1.2/tests/test_licensing.py +281 -0
  190. scholion-0.1.2/tests/test_limits.py +246 -0
  191. scholion-0.1.2/tests/test_localized_fields.py +198 -0
  192. scholion-0.1.2/tests/test_marker_resolution.py +184 -0
  193. scholion-0.1.2/tests/test_marker_schema.py +174 -0
  194. scholion-0.1.2/tests/test_math.py +62 -0
  195. scholion-0.1.2/tests/test_network_inventory.py +87 -0
  196. scholion-0.1.2/tests/test_output_language.py +82 -0
  197. scholion-0.1.2/tests/test_owner_split.py +126 -0
  198. scholion-0.1.2/tests/test_parity.py +42 -0
  199. scholion-0.1.2/tests/test_pgx_script_coordinates.py +141 -0
  200. scholion-0.1.2/tests/test_privacy_guard.py +144 -0
  201. scholion-0.1.2/tests/test_radar_coverage.py +160 -0
  202. scholion-0.1.2/tests/test_redact.py +194 -0
  203. scholion-0.1.2/tests/test_repo_hygiene.py +358 -0
  204. scholion-0.1.2/tests/test_safety_rules.py +136 -0
  205. scholion-0.1.2/tests/test_series_break.py +81 -0
  206. scholion-0.1.2/tests/test_server_guard.py +144 -0
  207. scholion-0.1.2/tests/test_showcase.py +233 -0
  208. scholion-0.1.2/tests/test_skill_editions.py +290 -0
  209. scholion-0.1.2/tests/test_tls_policy.py +149 -0
  210. 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.