Skip to content

Commit bcba77d

Browse files
docs: add TOX.md and relax the review rule to solo self-merge
Aroma and mouthfeel each have a canonical modality doc; the head family that most needs careful framing had none. docs/TOX.md covers the twelve Tox21 heads: why they differ from the flavor heads (wet-lab assay measurements vs documented percepts), why they are deliberately excluded from the substitute-match vector, why the Tox21 training molecules are NOT imported into the flavor universe, the per-assay CV-AUROC table (0.72-0.90), the featurization gotcha (bare 2048-bit Morgan, not the _feat block), where it surfaces, and the honest limits — assay activity is not toxicity. CONTRIBUTING: the documented "one approval, routed by CODEOWNERS" rule cannot be satisfied while the lead is the sole contributor (GitHub blocks self-approval and branch protection requires 0 approvals), so it now states self-merge on green CI, with a note to restore the approval requirement — in the doc AND in branch protection — as soon as a second contributor is active. Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
1 parent 321c4e8 commit bcba77d

3 files changed

Lines changed: 100 additions & 1 deletion

File tree

CONTRIBUTING.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ docs(data): document ChemTastesDB column names
4141
- **Small** — one logical change, readable as a sequence of decisions.
4242
- **Link the issue:** `Closes #42`.
4343
- **CI green** before merge.
44-
- **One approval required**, routed by [`CODEOWNERS`](CODEOWNERS).
44+
- **Review:** while the project has a single active contributor, the lead **self-merges** once CI
45+
is green (GitHub does not allow approving your own PR, and branch protection currently requires
46+
0 approvals). As soon as a second contributor is active, this reverts to **one required
47+
approval**, routed by [`CODEOWNERS`](CODEOWNERS) — flip
48+
`required_approving_review_count` to 1 on `main` at the same time so the rule is enforced, not
49+
just documented.
4550
- **Squash-merge**; the branch is deleted on merge. Full commit-by-commit detail
4651
and the review thread stay preserved in the PR.
4752
- For genuine pair work, add `Co-authored-by:` trailers so everyone gets credit.

docs/CAPABILITIES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ by how it's derived, and nothing claims more certainty than its source supports.
6767
- **In-vitro tox-assay flags** — 12 Tox21 assays (genotoxic-stress SR-p53/SR-ATAD5, AhR,
6868
mitochondrial, endocrine), `predict_tox()` (**trained**, Tox21 public domain; CV-AUROC
6969
**0.72–0.90**, surfaced per assay). INDICATIVE activity for review, **never a determination**.
70+
Assay activity is not toxicity, and these heads are deliberately kept OUT of the flavor-match
71+
vector. See [`TOX.md`](TOX.md).
7072
- Preliminary TTC concern tier (**qualitative** heuristic; Toxtree for the real call).
7173
- EU declarable fragrance-allergen labeling flag — `labeling()` (**lookup**, curated subset).
7274

docs/TOX.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Tox — caution-only in-vitro assay heads
2+
3+
Flavormancer predicts **flavor** ([`AROMA.md`](AROMA.md), [`MOUTHFEEL.md`](MOUTHFEEL.md)). This
4+
documents the fourth head family, which is **not** a flavor dimension: twelve **Tox21 in-vitro
5+
assay** heads that act as a *defensive screen*.
6+
7+
> **Read this first.** These heads predict whether a molecule would likely be **active in a
8+
> particular in-vitro assay**. Assay activity is **not** toxicity. A flag here means
9+
> *"a human should look at this"* — it is **never** a toxicity finding, a safety determination, a
10+
> hazard classification, or a clearance for use. Flavormancer flags for review; it does not clear
11+
> compounds. Confirm with a toxicologist and the applicable regulatory process.
12+
13+
## Why this is different from the flavor heads
14+
15+
| | flavor heads (taste / aroma / mouthfeel) | tox heads |
16+
|---|---|---|
17+
| label source | **documented + curated** sensory facts (a molecule is *known to be perceived* as X) | **experimental wet-lab screening** (a molecule *measurably was* active in an assay) |
18+
| what a positive means | people report this percept | this well lit up in a dish |
19+
| in the substitute-match vector? | **yes** (175 dims) | **no** — deliberately |
20+
| framing | prediction | **caution-only review flag** |
21+
22+
Tox is excluded from the flavor-profile vector on purpose: you do not want reformulation
23+
substitutes ranked by *shared toxicity signal*. The tox heads run per read and are stored per
24+
molecule for display and filtering, but they never influence what counts as a flavor match.
25+
26+
## Data — Tox21 (public domain)
27+
28+
**Tox21** is a US federal collaboration (**NIH/NCATS · EPA · FDA · NTP**) that quantitatively
29+
screened roughly 8k compounds against 12 in-vitro assays — nuclear-receptor signalling and
30+
stress-response pathways. We use the **MoleculeNet mirror of the public-domain Tox21 Challenge
31+
set** (`tox21.csv`), which carries a measured active/inactive call per compound per assay.
32+
33+
Public domain, US-government-produced (17 U.S.C. §105) — commercial-clean, same discipline as the
34+
rest of the corpus (see [`SOURCES.md`](SOURCES.md)).
35+
36+
**The Tox21 molecules are NOT imported into the flavor universe.** They are mostly industrial and
37+
pharmaceutical compounds — pesticides, drug-likes — and folding them into the molecule universe
38+
would pollute the flavor map, the enrichment table and the substitute search. Tox21 is a
39+
*predictor we apply to our universe*, not new members of it.
40+
41+
## Model
42+
43+
One `RandomForestClassifier` per assay (`n_estimators=200`, `class_weight="balanced"`,
44+
`random_state=42`), trained by `train_tox.py`. An assay ships only if it has **≥30 positives**;
45+
each reports an honest **5-fold CV-AUROC**, written to `tox_models/manifest.json` and surfaced in
46+
the UI next to the bar so nothing reads as more certain than it is.
47+
48+
⚠️ **Featurization differs from the flavor heads.** Tox heads take the **bare 2048-bit Morgan
49+
fingerprint** (`predict._fp`, radius 2), *not* the fingerprint + physicochemical block
50+
(`predict._feat`) that taste/aroma/mouthfeel use. Feeding a tox head `_feat` output raises a
51+
shape error (2060 vs 2048 features) — batch callers must build a separate matrix.
52+
53+
## The twelve heads
54+
55+
| assay | what it probes | CV-AUROC | positives / n |
56+
|---|---|---|---|
57+
| **NR-AhR** | aryl-hydrocarbon receptor (xenobiotic / dioxin-like) | 0.900 | 768 / 6542 |
58+
| **SR-MMP** | mitochondrial membrane potential (mitochondrial toxicity) | 0.878 | 918 / 5804 |
59+
| **NR-AR-LBD** | androgen receptor (ligand-binding domain) | 0.868 | 237 / 6751 |
60+
| **SR-ATAD5** | ATAD5 — genotoxicity / DNA damage | 0.850 | 264 / 7065 |
61+
| **SR-p53** | p53 — DNA-damage response (genotoxic stress) | 0.848 | 423 / 6767 |
62+
| **NR-PPAR-gamma** | PPAR-γ (metabolic) | 0.829 | 186 / 6443 |
63+
| **NR-ER-LBD** | estrogen receptor (ligand-binding domain) | 0.815 | 349 / 6948 |
64+
| **NR-Aromatase** | aromatase (estrogen synthesis) | 0.810 | 300 / 5815 |
65+
| **NR-AR** | androgen receptor | 0.808 | 308 / 7258 |
66+
| **SR-ARE** | oxidative-stress response (ARE) | 0.799 | 942 / 5825 |
67+
| **SR-HSE** | heat-shock response | 0.790 | 372 / 6460 |
68+
| **NR-ER** | estrogen receptor | 0.719 | 791 / 6186 |
69+
70+
All twelve clear the project's 0.70 bar. `NR-ER` sits closest to it — treat its flags with the
71+
least confidence of the set.
72+
73+
## Where it surfaces
74+
75+
- **Read modal** — a *Safety* group in the Heads card: every assay as a ranked %-bar with its
76+
CV-AUROC, amber-red once an assay crosses 0.5, under a caution-only note.
77+
- **`predict()`**`safety.tox_screen` (`assays[]` with `probability`, `auroc`, plain-language
78+
`meaning`; plus the `flags` shortlist at ≥0.5).
79+
- **`master_enrichment.parquet`**`tox_<assay>` columns plus a comma-separated `tox_flags`, so
80+
the universe grid is sortable/filterable by safety signal. 1,817 of 8,847 molecules carry ≥1 flag.
81+
- **MCP / skill**`read_flavor` and the CLI `read` return `tox_flags`.
82+
83+
## Honest limits
84+
85+
- **Assay activity ≠ toxicity.** No dose, no exposure route, no ADME, no in-vivo endpoint.
86+
- **In-vitro only**, and only these twelve pathways — silence here is *not* evidence of safety.
87+
- Trained on a largely industrial/pharmaceutical chemical space; flavor molecules are often
88+
outside that distribution, so treat out-of-domain reads with extra care.
89+
- Structure-only: no metabolite, impurity or degradation-product screening.
90+
- The separate **structural alert** screen, **TTC/Cramer** tier, **food-use lookup** and **EU
91+
allergen labeling** are complementary and equally caution-only — see
92+
[`CAPABILITIES.md`](CAPABILITIES.md).

0 commit comments

Comments
 (0)