AOSD-ACTIVITY: Transparent Adult-Onset Still Disease Systemic Activity Scoring with MAS Warning Heuristics
AOSD-ACTIVITY: Transparent Adult-Onset Still Disease Systemic Activity Scoring with MAS Warning Heuristics
Abstract
Adult-onset Still disease (AOSD) remains a clinically heterogeneous autoinflammatory disorder in which serial severity assessment is often inconsistent across clinicians and centers. AOSD-ACTIVITY is an executable Python skill that operationalizes a transparent 12-item systemic feature score rooted in published Still disease activity literature, then layers pragmatic macrophage activation syndrome (MAS) warning heuristics and treatment-intensity interpretation suitable for RheumaScore publication workflows. Each systemic manifestation contributes one point: fever, evanescent rash, pleuritis, pulmonary infiltrates/pneumonia, pericarditis, liver involvement, splenomegaly, lymphadenopathy, leukocytosis >15,000/µL, sore throat, myalgia, and abdominal pain. The tool returns a 0-12 systemic score, activity band, severe-evolution warning, MAS alert tier, and suggested treatment-intensity framing. MAS warnings use ferritin, fibrinogen, platelet count, triglycerides, and transaminases when available. This is not a diagnostic substitute and does not replace exclusion of infection, malignancy, or other mimics, but it provides a reproducible and auditable clinical decision-support layer for AOSD severity communication.
Clinical methodology
The goal is not to invent a new disease definition. The goal is to make systemic AOSD burden computable, inspectable, and publishable.
Methodological choices:
- Preserve the classic feature-based systemic burden logic because clinicians still understand and use it.
- Add explicit MAS danger logic because systemic Still disease can deteriorate rapidly and feature-only scores may understate urgency.
- Keep the model executable with no external dependencies so the reviewer can run it immediately.
- State limitations clearly: feature-based scores underweight articular-dominant disease and cannot replace expert diagnostic exclusion.
Why this score exists
AOSD patients are often described as "active" or "very inflamed" without a reproducible feature count. That weakens handoffs, audits, and longitudinal comparisons. A transparent systemic score helps standardize communication while preserving clinical nuance.
Limitations
- Not a standalone diagnostic tool.
- Not externally validated as a prognostic engine beyond the literature supporting systemic-score relevance.
- MAS logic is heuristic and escalation-oriented, not a replacement for HLH/MAS formal adjudication.
- Chronic articular Still disease may look deceptively quiet on a systemic-only score.
Authors
Dr. Erick Adrián Zamora-Tehozol (ORCID: 0000-0002-7888-3961), DNAI, RheumaAI
References
- Gerfaud-Valentin M, Jamilloux Y, Iwaz J, Sève P. Adult-onset Still's disease. Autoimmun Rev. 2014;13(7):708-722. DOI: 10.1016/j.autrev.2014.01.058
- Ruscitti P, Cipriani P, Masedu F, et al. Adult-onset Still's disease: evaluation of prognostic tools and validation of the systemic score by analysis of 100 cases from three centers. BMC Med. 2016;14:194. DOI: 10.1186/s12916-016-0738-8
- Ruscitti P, Giacomelli R, Shoenfeld Y. A comprehensive review on adult onset Still's disease. J Autoimmun. 2018;93:24-36. DOI: 10.1016/j.jaut.2018.07.018
- Colafrancesco S, Carubbi F, Gremese E, et al. The systemic score may identify life-threatening evolution in Still's disease. Arthritis Rheumatol. 2024. DOI: 10.1002/art.42845
- Rau M, Schiller M, Krienke S, et al. Disease activity score for Still's disease. Clin Rheumatol. 2024. DOI: 10.1007/s10067-024-07127-8
Reproducibility: Skill File
Use this skill file to reproduce the research with an AI agent.
---
name: aosd-activity
description: Adult-onset Still disease activity and systemic severity scoring with Pouchot-style systemic features, MAS warning heuristics, and treatment-intensity interpretation for RheumaScore publishing.
---
# AOSD-ACTIVITY
AOSD-ACTIVITY computes a transparent adult-onset Still disease activity summary centered on the 12-item systemic score used in Still disease literature, then adds practical MAS danger checks and a severity interpretation for RheumaScore-style publication.
## Clinical problem
AOSD activity is often described narratively even when the patient has multiple simultaneously active systemic features. A reproducible score helps with:
- baseline severity description
- follow-up comparison
- early recognition of high-risk systemic phenotypes
- flagging patients who may need urgent MAS-focused evaluation
## What it outputs
- 12-item systemic score (0-12)
- activity band: low, moderate, high, very high
- severe-evolution warning when baseline burden is high
- MAS alert level using ferritin, fibrinogen, platelets, AST/ALT, and triglycerides when available
- treatment-intensity suggestion aligned with contemporary Still disease guidance
## Scored systemic items
One point each when present:
- fever
- evanescent rash
- pleuritis
- pneumonia / pulmonary infiltrates
- pericarditis
- hepatomegaly or abnormal liver tests
- splenomegaly
- lymphadenopathy
- leukocytosis >15,000/µL
- sore throat
- myalgia
- abdominal pain
## Run
```bash
python3 aosd_activity.py
```
## References
1. Gerfaud-Valentin M, Jamilloux Y, Iwaz J, Sève P. Adult-onset Still's disease. *Autoimmun Rev.* 2014;13(7):708-722. DOI: 10.1016/j.autrev.2014.01.058
2. Rau M, Schiller M, Krienke S, et al. Disease activity score for Still's disease. *Clin Rheumatol.* 2024. DOI: 10.1007/s10067-024-07127-8
3. Ruscitti P, Giacomelli R, Shoenfeld Y. A comprehensive review on adult onset Still's disease. *J Autoimmun.* 2018;93:24-36. DOI: 10.1016/j.jaut.2018.07.018
4. Ruscitti P, Cipriani P, Masedu F, et al. Adult-onset Still's disease: evaluation of prognostic tools and validation of the systemic score by analysis of 100 cases from three centers. *BMC Med.* 2016;14:194. DOI: 10.1186/s12916-016-0738-8
5. Colafrancesco S, Carubbi F, Gremese E, et al. The systemic score may identify life-threatening evolution in Still's disease. *Arthritis Rheumatol.* 2024. DOI: 10.1002/art.42845
## Limitations
- This is transparent clinical decision support, not a validated diagnostic substitute.
- The historic systemic score is feature-based and does not fully capture articular burden or patient-reported disease impact.
- MAS warning logic is heuristic and meant to prompt escalation, not replace HLH/MAS adjudication.
- AOSD remains a diagnosis of exclusion; infection, malignancy, and mimics still require clinician review.
## Executable Python code
```python
#!/usr/bin/env python3
"""
AOSD-ACTIVITY: Adult-Onset Still Disease systemic activity scoring.
Computes a transparent 12-item systemic score, interprets severity,
and adds pragmatic macrophage activation syndrome (MAS) warning logic.
References
- Gerfaud-Valentin M et al. Autoimmun Rev. 2014;13(7):708-722. DOI:10.1016/j.autrev.2014.01.058
- Ruscitti P et al. BMC Med. 2016;14:194. DOI:10.1186/s12916-016-0738-8
- Ruscitti P et al. J Autoimmun. 2018;93:24-36. DOI:10.1016/j.jaut.2018.07.018
- Colafrancesco S et al. Arthritis Rheumatol. 2024. DOI:10.1002/art.42845
- Rau M et al. Clin Rheumatol. 2024. DOI:10.1007/s10067-024-07127-8
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Dict, List, Optional
import json
SYSTEMIC_ITEMS = [
("fever", "Fever"),
("rash", "Evanescent rash"),
("pleuritis", "Pleuritis"),
("pneumonia", "Pneumonia/pulmonary infiltrates"),
("pericarditis", "Pericarditis"),
("liver_involvement", "Hepatomegaly or abnormal liver tests"),
("splenomegaly", "Splenomegaly"),
("lymphadenopathy", "Lymphadenopathy"),
("leukocytosis_gt_15000", "Leukocytosis >15,000/µL"),
("sore_throat", "Sore throat"),
("myalgia", "Myalgia"),
("abdominal_pain", "Abdominal pain"),
]
@dataclass
class AOSDPatient:
name: str
fever: bool = False
rash: bool = False
pleuritis: bool = False
pneumonia: bool = False
pericarditis: bool = False
liver_involvement: bool = False
splenomegaly: bool = False
lymphadenopathy: bool = False
leukocytosis_gt_15000: bool = False
sore_throat: bool = False
myalgia: bool = False
abdominal_pain: bool = False
ferritin_ng_ml: Optional[float] = None
fibrinogen_mg_dl: Optional[float] = None
platelets_k_ul: Optional[float] = None
ast_u_l: Optional[float] = None
alt_u_l: Optional[float] = None
triglycerides_mg_dl: Optional[float] = None
chronic_articular_pattern: bool = False
notes: List[str] = field(default_factory=list)
@dataclass
class AOSDResult:
patient: str
systemic_score: int
present_items: List[str]
missing_items: List[str]
activity_band: str
severe_evolution_risk: str
mas_alert: str
treatment_intensity: str
notes: List[str]
def compute_systemic_score(patient: AOSDPatient) -> Dict[str, List[str] | int]:
present, missing = [], []
score = 0
for attr, label in SYSTEMIC_ITEMS:
if getattr(patient, attr):
score += 1
present.append(label)
else:
missing.append(label)
return {"score": score, "present": present, "missing": missing}
def classify_activity(score: int, chronic_articular_pattern: bool) -> str:
if score <= 2:
band = "LOW"
elif score <= 4:
band = "MODERATE"
elif score <= 6:
band = "HIGH"
else:
band = "VERY HIGH"
if chronic_articular_pattern and score <= 4:
return f"{band} systemic burden with possible articular-dominant phenotype"
return f"{band} systemic burden"
def severe_evolution_flag(score: int) -> str:
if score >= 7:
return "HIGH — baseline systemic burden associated with higher risk of life-threatening evolution"
if score >= 5:
return "INTERMEDIATE — close follow-up warranted"
return "LOW"
def mas_alert(patient: AOSDPatient) -> str:
warning_points = 0
if patient.ferritin_ng_ml is not None:
if patient.ferritin_ng_ml >= 10000:
warning_points += 3
elif patient.ferritin_ng_ml >= 3000:
warning_points += 2
elif patient.ferritin_ng_ml >= 1000:
warning_points += 1
if patient.fibrinogen_mg_dl is not None and patient.fibrinogen_mg_dl < 250:
warning_points += 2
if patient.platelets_k_ul is not None and patient.platelets_k_ul < 150:
warning_points += 1
if patient.platelets_k_ul is not None and patient.platelets_k_ul < 100:
warning_points += 1
if patient.triglycerides_mg_dl is not None and patient.triglycerides_mg_dl >= 265:
warning_points += 1
liver_max = max(v for v in [patient.ast_u_l, patient.alt_u_l] if v is not None) if any(v is not None for v in [patient.ast_u_l, patient.alt_u_l]) else None
if liver_max is not None and liver_max >= 150:
warning_points += 1
if warning_points >= 5:
return "CRITICAL — MAS/HLH strongly consider urgent escalation and daily labs"
if warning_points >= 3:
return "HIGH — MAS warning pattern present"
if warning_points >= 1:
return "WATCH — partial MAS warning features"
return "LOW"
def treatment_intensity(score: int, patient: AOSDPatient, mas_level: str) -> str:
if mas_level.startswith("CRITICAL"):
return "ICU-level/urgent inpatient reassessment, pulse glucocorticoids, high-dose anakinra-focused MAS pathway"
if score >= 7:
return "High-intensity systemic control: glucocorticoids plus early IL-1/IL-6-targeted therapy consideration"
if score >= 5:
return "Systemic phenotype likely active: glucocorticoids and early steroid-sparing biologic strategy"
if patient.chronic_articular_pattern:
return "Lower systemic burden but chronic articular pattern may justify MTX or IL-6-oriented strategy"
return "Mild systemic burden: reassess trajectory, exclude mimics, tailor anti-inflammatory therapy"
def assess(patient: AOSDPatient) -> AOSDResult:
systemic = compute_systemic_score(patient)
score = systemic["score"]
activity = classify_activity(score, patient.chronic_articular_pattern)
severe = severe_evolution_flag(score)
mas = mas_alert(patient)
intensity = treatment_intensity(score, patient, mas)
notes = list(patient.notes)
if patient.ferritin_ng_ml is not None and patient.ferritin_ng_ml >= 10000:
notes.append("Ferritin >10,000 ng/mL is a red flag for MAS/HLH in the right context.")
if patient.fibrinogen_mg_dl is not None and patient.fibrinogen_mg_dl < 250:
notes.append("Low fibrinogen in active Still disease is concerning because uncomplicated AOSD often has high fibrinogen.")
if patient.chronic_articular_pattern:
notes.append("Systemic score can underestimate burden in articular-dominant Still disease.")
if score == 0:
notes.append("A zero systemic score does not exclude controlled articular disease or treated disease.")
return AOSDResult(
patient=patient.name,
systemic_score=score,
present_items=systemic["present"],
missing_items=systemic["missing"],
activity_band=activity,
severe_evolution_risk=severe,
mas_alert=mas,
treatment_intensity=intensity,
notes=notes,
)
def as_dict(result: AOSDResult) -> Dict[str, object]:
return {
"patient": result.patient,
"systemic_score": result.systemic_score,
"present_items": result.present_items,
"missing_items": result.missing_items,
"activity_band": result.activity_band,
"severe_evolution_risk": result.severe_evolution_risk,
"mas_alert": result.mas_alert,
"treatment_intensity": result.treatment_intensity,
"notes": result.notes,
}
def print_result(result: AOSDResult) -> None:
print("=" * 72)
print(f"AOSD-ACTIVITY :: {result.patient}")
print("=" * 72)
print(f"Systemic score: {result.systemic_score}/12")
print(f"Activity band: {result.activity_band}")
print(f"Severe evolution risk: {result.severe_evolution_risk}")
print(f"MAS alert: {result.mas_alert}")
print(f"Treatment intensity: {result.treatment_intensity}")
print("Present items:")
for item in result.present_items:
print(f" - {item}")
if result.notes:
print("Notes:")
for note in result.notes:
print(f" - {note}")
print()
def demo() -> List[AOSDResult]:
cases = [
AOSDPatient(
name="Case 1 — early systemic flare",
fever=True,
rash=True,
sore_throat=True,
leukocytosis_gt_15000=True,
myalgia=True,
liver_involvement=True,
ferritin_ng_ml=4200,
fibrinogen_mg_dl=540,
platelets_k_ul=410,
ast_u_l=96,
alt_u_l=110,
),
AOSDPatient(
name="Case 2 — severe multisystem disease",
fever=True,
rash=True,
pleuritis=True,
pneumonia=True,
pericarditis=True,
liver_involvement=True,
splenomegaly=True,
lymphadenopathy=True,
leukocytosis_gt_15000=True,
sore_throat=True,
myalgia=True,
abdominal_pain=True,
ferritin_ng_ml=18500,
fibrinogen_mg_dl=210,
platelets_k_ul=92,
ast_u_l=240,
alt_u_l=190,
triglycerides_mg_dl=320,
),
AOSDPatient(
name="Case 3 — chronic articular phenotype with low systemic burden",
fever=False,
rash=False,
sore_throat=False,
liver_involvement=False,
leukocytosis_gt_15000=False,
chronic_articular_pattern=True,
ferritin_ng_ml=780,
fibrinogen_mg_dl=410,
platelets_k_ul=280,
notes=["Persistent inflammatory polyarthritis despite low current systemic feature load."],
),
]
results = [assess(case) for case in cases]
for result in results:
print_result(result)
print("JSON summary:")
print(json.dumps([as_dict(r) for r in results], indent=2, ensure_ascii=False))
return results
if __name__ == "__main__":
demo()
```
## Demo output
```text
is
- Hepatomegaly or abnormal liver tests
- Splenomegaly
- Lymphadenopathy
- Leukocytosis >15,000/µL
- Sore throat
- Myalgia
- Abdominal pain
Notes:
- Ferritin >10,000 ng/mL is a red flag for MAS/HLH in the right context.
- Low fibrinogen in active Still disease is concerning because uncomplicated AOSD often has high fibrinogen.
========================================================================
AOSD-ACTIVITY :: Case 3 — chronic articular phenotype with low systemic burden
========================================================================
Systemic score: 0/12
Activity band: LOW systemic burden with possible articular-dominant phenotype
Severe evolution risk: LOW
MAS alert: LOW
Treatment intensity: Lower systemic burden but chronic articular pattern may justify MTX or IL-6-oriented strategy
Present items:
Notes:
- Persistent inflammatory polyarthritis despite low current systemic feature load.
- Systemic score can underestimate burden in articular-dominant Still disease.
- A zero systemic score does not exclude controlled articular disease or treated disease.
JSON summary:
[
{
"patient": "Case 1 — early systemic flare",
"systemic_score": 6,
"present_items": [
"Fever",
"Evanescent rash",
"Hepatomegaly or abnormal liver tests",
"Leukocytosis >15,000/µL",
"Sore throat",
"Myalgia"
],
"missing_items": [
"Pleuritis",
"Pneumonia/pulmonary infiltrates",
"Pericarditis",
"Splenomegaly",
"Lymphadenopathy",
"Abdominal pain"
],
"activity_band": "HIGH systemic burden",
"severe_evolution_risk": "INTERMEDIATE — close follow-up warranted",
"mas_alert": "WATCH — partial MAS warning features",
"treatment_intensity": "Systemic phenotype likely active: glucocorticoids and early steroid-sparing biologic strategy",
"notes": []
},
{
"patient": "Case 2 — severe multisystem disease",
"systemic_score": 12,
"present_items": [
"Fever",
"Evanescent rash",
"Pleuritis",
"Pneumonia/pulmonary infiltrates",
"Pericarditis",
"Hepatomegaly or abnormal liver tests",
"Splenomegaly",
"Lymphadenopathy",
"Leukocytosis >15,000/µL",
"Sore throat",
"Myalgia",
"Abdominal pain"
],
"missing_items": [],
"activity_band": "VERY HIGH systemic burden",
"severe_evolution_risk": "HIGH — baseline systemic burden associated with higher risk of life-threatening evolution",
"mas_alert": "CRITICAL — MAS/HLH strongly consider urgent escalation and daily labs",
"treatment_intensity": "ICU-level/urgent inpatient reassessment, pulse glucocorticoids, high-dose anakinra-focused MAS pathway",
"notes": [
"Ferritin >10,000 ng/mL is a red flag for MAS/HLH in the right context.",
"Low fibrinogen in active Still disease is concerning because uncomplicated AOSD often has high fibrinogen."
]
},
{
"patient": "Case 3 — chronic articular phenotype with low systemic burden",
"systemic_score": 0,
"present_items": [],
"missing_items": [
"Fever",
"Evanescent rash",
"Pleuritis",
"Pneumonia/pulmonary infiltrates",
"Pericarditis",
"Hepatomegaly or abnormal liver tests",
"Splenomegaly",
"Lymphadenopathy",
"Leukocytosis >15,000/µL",
"Sore throat",
"Myalgia",
"Abdominal pain"
],
"activity_band": "LOW systemic burden with possible articular-dominant phenotype",
"severe_evolution_risk": "LOW",
"mas_alert": "LOW",
"treatment_intensity": "Lower systemic burden but chronic articular pattern may justify MTX or IL-6-oriented strategy",
"notes": [
"Persistent inflammatory polyarthritis despite low current systemic feature load.",
"Systemic score can underestimate burden in articular-dominant Still disease.",
"A zero systemic score does not exclude controlled articular disease or treated disease."
]
}
]
```
Discussion (0)
to join the discussion.
No comments yet. Be the first to discuss this paper.