fix(tooling): body_definition_parser no longer configures logging on import

A module-level logging.basicConfig(level=INFO) ran whenever any reach verb
imported the parser. That configured root logging process-wide and wrote plain
text to stderr, breaking reach's contract that stderr carries only JSONL events
and one verdict. A dry run of bake-biome emitted 205 KB this way, most of it a
line per body of every parsed system.

Its eight log calls now go through console.event. Per-body and per-system lines
become debug, visible only with verbose output. The four warnings stay warn, as
structured events: 66 of them across the bake scope, each an authored orbit
that contradicts the body's planet class ("too hot for temperate").
Those are real data findings and stay visible. A dry run is now two lines
plus those warnings.

Also: tooling/core/command.py carried the same two-line comment twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-25 15:55:53 +02:00
co-authored by Claude Opus 5.5
parent 76e3f3ec96
commit 1857c6405e
2 changed files with 15 additions and 18 deletions
-2
View File
@@ -57,8 +57,6 @@ def command(func: F) -> F:
@functools.wraps(func)
def wrapped(*args: Any, **kwargs: Any) -> Any:
# A detached child adopts the id its parent already reported; a
# foreground run mints a fresh one.
# A detached child adopts the id its parent already reported; a
# foreground run mints a fresh one.
token = jobs.begin(os.environ.get(jobs.ENV_JOB_ID))
@@ -37,7 +37,6 @@ Override file format:
import argparse
import hashlib
import json
import logging
import math
import os
import re
@@ -49,8 +48,6 @@ import numpy as np
from tooling.core import console
from tooling.domains.atlas.planet.biome_config import GAS_PALETTE_SELECTION as GAS_PALETTES
logging.basicConfig(level=logging.INFO, format=" %(levelname)s %(message)s")
log = logging.getLogger(__name__)
# ---------------------------------------------------------------------------
# Constants / lookup tables
@@ -313,12 +310,14 @@ def _check_habitability(body_def: dict) -> None:
gh = {"none": 0, "thin": 8, "standard": 33, "thick": 80}.get(atmo, 33)
t_eq = 278.5 * (lum ** 0.25) / math.sqrt(max(dist, 0.01)) + gh
if t_eq > 340:
log.warning(f" {body_def['id']}: T_eq={t_eq:.0f}K ({t_eq-273:.0f}°C) — "
f"too hot for {pclass}. Check distance_au ({dist:.2f} AU). "
f"Habitable zone ≈ {(278.5*(lum**0.25)/(290-gh))**2:.2f} AU")
console.event(f"{body_def['id']}: T_eq={t_eq:.0f}K ({t_eq-273:.0f}°C) — "
f"too hot for {pclass}. Check distance_au ({dist:.2f} AU). "
f"Habitable zone ≈ {(278.5*(lum**0.25)/(290-gh))**2:.2f} AU",
level="warn")
elif t_eq < 220:
log.warning(f" {body_def['id']}: T_eq={t_eq:.0f}K ({t_eq-273:.0f}°C) — "
f"too cold for {pclass}. Check distance_au ({dist:.2f} AU).")
console.event(f"{body_def['id']}: T_eq={t_eq:.0f}K ({t_eq-273:.0f}°C) — "
f"too cold for {pclass}. Check distance_au ({dist:.2f} AU).",
level="warn")
def _is_tidally_locked(period_days: float, star_type: str) -> bool:
@@ -373,7 +372,7 @@ def _parse_bodies_table(md_text: str) -> list[dict]:
md_text, re.DOTALL
)
if not table_match:
log.warning("No bodies table found in markdown")
console.event("No bodies table found in markdown", level="warn")
return []
table_body = table_match.group(2)
@@ -482,7 +481,7 @@ def _build_body_def(
else:
planet_class = PLANET_CLASS_MAP.get(biome, "temperate")
if biome and biome not in PLANET_CLASS_MAP and biome != "—":
log.warning(f" {bid}: unknown planet class '{biome}' — defaulting to temperate")
console.event(f" {bid}: unknown planet class '{biome}' — defaulting to temperate", level="warn")
planet_class = ov.get("planet_class", planet_class)
@@ -781,12 +780,12 @@ def parse_system(
# Parse star
star = _parse_star(md_text)
log.info(f"System: {system_id} Star: {star['type']}-type "
f"L={star['luminosity_solar']:.3g} Lsun")
console.event(f"System: {system_id} Star: {star['type']}-type "
f"L={star['luminosity_solar']:.3g} Lsun", level="debug")
# Parse bodies table
rows = _parse_bodies_table(md_text)
log.info(f"Found {len(rows)} renderable bodies")
console.event(f"Found {len(rows)} renderable bodies", level="debug")
# Track which bodies are moons of gas giants (for tidal heating)
# Simple heuristic: if the previous non-moon row was a gas_giant, this is its moon
@@ -815,9 +814,9 @@ def parse_system(
continue
body_defs.append(body_def)
log.info(f" {bid:20s} {body_def['planet_class']:20s} "
console.event(f" {bid:20s} {body_def['planet_class']:20s} "
f"scale={body_def['body_scale']:6s} "
f"seed={body_def['seed']}")
f"seed={body_def['seed']}", level="debug")
_check_habitability(body_def)
# Write output files
@@ -827,7 +826,7 @@ def parse_system(
out_path = os.path.join(out_dir, f"{bd['id']}_def.json")
with open(out_path, "w") as f:
json.dump(bd, f, indent=2)
log.info(f"Wrote {len(body_defs)} body definitions → {out_dir}/")
console.event(f"Wrote {len(body_defs)} body definitions → {out_dir}/")
return body_defs