Spaces:
Sleeping
Sleeping
release: v1.8.2 ICH M15 citation alignment
Browse files- stem_ai/render_html.py +32 -11
stem_ai/render_html.py
CHANGED
|
@@ -218,14 +218,17 @@ def _code_integrity_summary(integrity: dict[str, Any]) -> tuple[list[tuple[str,
|
|
| 218 |
|
| 219 |
|
| 220 |
def _section1(result: dict[str, Any], final: int, tc: str,
|
| 221 |
-
s1: int, s2: int, s3: int, s4: int, t0: bool
|
|
|
|
| 222 |
score = result["score"]
|
| 223 |
calibration = result.get("calibration_profile", {})
|
|
|
|
| 224 |
freshness = result.get("audit_freshness", {})
|
| 225 |
policy_name = xt(str(calibration.get("profile_name", "unknown")))
|
| 226 |
policy_status = xt(str(calibration.get("profile_status", "unknown")))
|
| 227 |
policy_mode = xt(str(calibration.get("profile_read_mode", "unknown")))
|
| 228 |
calibration_note = _calibration_effect_note(calibration)
|
|
|
|
| 229 |
|
| 230 |
stats = "".join(
|
| 231 |
f'<div class="metric-card">'
|
|
@@ -244,13 +247,23 @@ def _section1(result: dict[str, Any], final: int, tc: str,
|
|
| 244 |
positives = result.get("notable_positive_evidence", [])[:4]
|
| 245 |
stage2_focus = _select_focus_rows(result.get("stage_2r_rubric", {}), negatives_first=True, limit=3)
|
| 246 |
stage3_focus = _select_focus_rows(result.get("stage_3_rubric", {}), negatives_first=False, limit=3)
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
risk_list = "".join(f'<li>{xt(str(r))}</li>' for r in risks) or "<li>No notable risks surfaced.</li>"
|
| 255 |
positive_list = "".join(f'<li>{xt(str(p))}</li>' for p in positives) or "<li>No notable positive evidence surfaced.</li>"
|
| 256 |
return (
|
|
@@ -303,6 +316,10 @@ def _section1(result: dict[str, Any], final: int, tc: str,
|
|
| 303 |
f'<div class="eyebrow">Policy Boundary</div>'
|
| 304 |
f'<h3>How to read this artifact</h3>'
|
| 305 |
f'<p class="memo-text">{xt(calibration_note) if calibration_note else "Authoritative scoring and surfaced policy metadata are aligned in this release line."}</p>'
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
f'</article>'
|
| 307 |
f'</div>'
|
| 308 |
f'</section>'
|
|
@@ -357,6 +374,8 @@ def _section2(result: dict[str, Any], s1: int, s2: int, s3: int, s4: int) -> str
|
|
| 357 |
stage2_focus = _select_focus_rows(result.get("stage_2r_rubric", {}), negatives_first=True, limit=4)
|
| 358 |
stage3_focus = _select_focus_rows(result.get("stage_3_rubric", {}), negatives_first=False, limit=4)
|
| 359 |
stage4_focus = _select_focus_rows(result.get("stage_4_rubric", {}), negatives_first=False, limit=4)
|
|
|
|
|
|
|
| 360 |
cards = "".join([
|
| 361 |
_stage_card(
|
| 362 |
"Stage 1 — README Intent",
|
|
@@ -380,7 +399,7 @@ def _section2(result: dict[str, Any], s1: int, s2: int, s3: int, s4: int) -> str
|
|
| 380 |
_C["slate"],
|
| 381 |
_STAGE_TIPS[2],
|
| 382 |
stage3_focus,
|
| 383 |
-
"Engineering accountability, provenance, and reviewable responsibility surfaces.",
|
| 384 |
),
|
| 385 |
_stage_card(
|
| 386 |
"Stage 4 — Replication",
|
|
@@ -625,11 +644,13 @@ def render_html(result: dict[str, Any]) -> str:
|
|
| 625 |
s2 = int(score.get("stage_2_repo_local_consistency", 0))
|
| 626 |
s3 = int(score.get("stage_3_code_bio", 0))
|
| 627 |
s4 = int(result.get("replication_score", 0))
|
| 628 |
-
|
|
|
|
|
|
|
| 629 |
|
| 630 |
css = build_css(tc)
|
| 631 |
hero = _hero(score, final, tier, tc, target, date)
|
| 632 |
-
sec1 = _section1(result, final, tc, s1, s2, s3, s4, t0)
|
| 633 |
sec2 = _section2(result, s1, s2, s3, s4)
|
| 634 |
sec3 = _section3(result.get("code_integrity", {}), result.get("code_contract", {}))
|
| 635 |
sec4 = _section4(result.get("airi_risk_coverage", {}))
|
|
|
|
| 218 |
|
| 219 |
|
| 220 |
def _section1(result: dict[str, Any], final: int, tc: str,
|
| 221 |
+
s1: int, s2: int, s3: int, s4: int, t0: bool,
|
| 222 |
+
score_cap: int | None = None) -> str:
|
| 223 |
score = result["score"]
|
| 224 |
calibration = result.get("calibration_profile", {})
|
| 225 |
+
cls = result.get("classification", {})
|
| 226 |
freshness = result.get("audit_freshness", {})
|
| 227 |
policy_name = xt(str(calibration.get("profile_name", "unknown")))
|
| 228 |
policy_status = xt(str(calibration.get("profile_status", "unknown")))
|
| 229 |
policy_mode = xt(str(calibration.get("profile_read_mode", "unknown")))
|
| 230 |
calibration_note = _calibration_effect_note(calibration)
|
| 231 |
+
ca_severity = cls.get("ca_severity", "none")
|
| 232 |
|
| 233 |
stats = "".join(
|
| 234 |
f'<div class="metric-card">'
|
|
|
|
| 247 |
positives = result.get("notable_positive_evidence", [])[:4]
|
| 248 |
stage2_focus = _select_focus_rows(result.get("stage_2r_rubric", {}), negatives_first=True, limit=3)
|
| 249 |
stage3_focus = _select_focus_rows(result.get("stage_3_rubric", {}), negatives_first=False, limit=3)
|
| 250 |
+
if t0:
|
| 251 |
+
alert = (
|
| 252 |
+
f'<div class="alert-t0">'
|
| 253 |
+
f'<strong>Tier Lock [T0-FLOOR]:</strong> Direct clinical framing without an explicit boundary declaration. '
|
| 254 |
+
f'Score ceiling at 39. Resolving this condition is required before any tier advancement.'
|
| 255 |
+
f'</div>'
|
| 256 |
+
)
|
| 257 |
+
elif score_cap is not None:
|
| 258 |
+
alert = (
|
| 259 |
+
f'<div class="alert-t0" style="background:#fff3cd;border-color:#ffc107;color:#856404;">'
|
| 260 |
+
f'<strong>Tier Lock [CA-CAP]:</strong> Clinical-adjacent surface detected without explicit non-clinical boundary. '
|
| 261 |
+
f'Score ceiling at {score_cap} (T2 maximum). '
|
| 262 |
+
f'Adding a non-diagnostic disclaimer resolves this lock.'
|
| 263 |
+
f'</div>'
|
| 264 |
+
)
|
| 265 |
+
else:
|
| 266 |
+
alert = ""
|
| 267 |
risk_list = "".join(f'<li>{xt(str(r))}</li>' for r in risks) or "<li>No notable risks surfaced.</li>"
|
| 268 |
positive_list = "".join(f'<li>{xt(str(p))}</li>' for p in positives) or "<li>No notable positive evidence surfaced.</li>"
|
| 269 |
return (
|
|
|
|
| 316 |
f'<div class="eyebrow">Policy Boundary</div>'
|
| 317 |
f'<h3>How to read this artifact</h3>'
|
| 318 |
f'<p class="memo-text">{xt(calibration_note) if calibration_note else "Authoritative scoring and surfaced policy metadata are aligned in this release line."}</p>'
|
| 319 |
+
f'<p class="memo-note"><strong>Classification applied:</strong> '
|
| 320 |
+
f'ca_severity={xt(ca_severity)} | '
|
| 321 |
+
f'score_cap={xt(str(score_cap)) if score_cap is not None else "none"} | '
|
| 322 |
+
f't0_floor={"active" if t0 else "clear"}</p>'
|
| 323 |
f'</article>'
|
| 324 |
f'</div>'
|
| 325 |
f'</section>'
|
|
|
|
| 374 |
stage2_focus = _select_focus_rows(result.get("stage_2r_rubric", {}), negatives_first=True, limit=4)
|
| 375 |
stage3_focus = _select_focus_rows(result.get("stage_3_rubric", {}), negatives_first=False, limit=4)
|
| 376 |
stage4_focus = _select_focus_rows(result.get("stage_4_rubric", {}), negatives_first=False, limit=4)
|
| 377 |
+
_s3r = result.get("stage_3_rubric", {}).get("stage_3_raw_total", {})
|
| 378 |
+
_s3_formula = f" (raw: {_s3r['score']}/{_s3r['max']})" if _s3r.get("score") is not None and _s3r.get("max") else ""
|
| 379 |
cards = "".join([
|
| 380 |
_stage_card(
|
| 381 |
"Stage 1 — README Intent",
|
|
|
|
| 399 |
_C["slate"],
|
| 400 |
_STAGE_TIPS[2],
|
| 401 |
stage3_focus,
|
| 402 |
+
f"Engineering accountability, provenance, and reviewable responsibility surfaces.{_s3_formula}",
|
| 403 |
),
|
| 404 |
_stage_card(
|
| 405 |
"Stage 4 — Replication",
|
|
|
|
| 644 |
s2 = int(score.get("stage_2_repo_local_consistency", 0))
|
| 645 |
s3 = int(score.get("stage_3_code_bio", 0))
|
| 646 |
s4 = int(result.get("replication_score", 0))
|
| 647 |
+
cls = result.get("classification", {})
|
| 648 |
+
t0 = cls.get("t0_hard_floor", False)
|
| 649 |
+
score_cap = cls.get("score_cap")
|
| 650 |
|
| 651 |
css = build_css(tc)
|
| 652 |
hero = _hero(score, final, tier, tc, target, date)
|
| 653 |
+
sec1 = _section1(result, final, tc, s1, s2, s3, s4, t0, score_cap)
|
| 654 |
sec2 = _section2(result, s1, s2, s3, s4)
|
| 655 |
sec3 = _section3(result.get("code_integrity", {}), result.get("code_contract", {}))
|
| 656 |
sec4 = _section4(result.get("airi_risk_coverage", {}))
|