"""CoreComposite - drillhole assay interval compositing engine. Deterministic, stdlib-only, Pyodide-safe. Proposed offline data-prep kit. Scope: recomputes the length-support basis of ALREADY-MEASURED assay values via exact interval-intersection length-weighted averaging (sweep overlap join). NOT a geological model, resource/reserve estimate, economic cutoff, grade control, or regulatory conformity tool. Missing observations are never zero-filled. """ from __future__ import annotations import csv, io, json, hashlib, math, os, sys, tempfile, base64, zipfile, html VERSION = "corecomposite-1.0.0" ALGORITHM = "exact interval-intersection length-weighted average (sweep overlap join)" TOL = 1e-9 MAX_ROWS = 10000 MAX_BOUNDS = 10000 MAX_BINS = 20000 MAX_CONTRIBUTORS = 100000 MAX_BYTES = 8 * 1024 * 1024 MAX_DEPTH = 12 MAX_NODES = 200000 MAX_STRING = 2048 MAX_HOLES = 1000 VALID_RESIDUAL = ("keep", "drop", "merge_last") VALID_CENSOR = ("error", "drop", "half", "limit") CSV_FILES = ("composites.csv", "contributors.csv", "coverage.csv", "excluded-intervals.csv") CORE_FILES = frozenset({"assays.csv", "settings.json"}) SCOPE = ("Recomputes length-support of measured assay values by exact interval " "intersection. No geological modelling, resource/reserve estimate, cutoff, " "or regulatory conformity. Missing values are never zero-filled.") COLUMNS = { "composites.csv": ["hole_id","bin","from","to","length","composite_value","coverage","low_coverage","n_contributors"], "contributors.csv": ["hole_id","bin","source_row","weight","value","contribution"], "coverage.csv": ["hole_id","bin","from","to","length","covered_length","coverage"], "excluded-intervals.csv": ["hole_id","source_row","from","to","excluded_length","value","reason"], } class CompositeError(Exception): def __init__(self, code, message, **ctx): super().__init__(message) self.code = code; self.message = message; self.ctx = ctx def _is_number(x): return isinstance(x, (int, float)) and not isinstance(x, bool) def _finite(x): try: return _is_number(x) and math.isfinite(float(x)) except (OverflowError, ValueError): return False def _classify_value(raw, missing_codes, censor_policy): if raw is None: return ("missing", None) if isinstance(raw, bool): raise CompositeError("bool_as_number", "boolean is not a valid assay value", value=str(raw)) if _is_number(raw): if not math.isfinite(float(raw)): raise CompositeError("nonfinite", "non-finite numeric value", value=str(raw)) return ("num", float(raw)) if isinstance(raw, str): s = raw.strip() if s in missing_codes: return ("missing", None) if s[:1] in ("<", ">"): if censor_policy == "error": raise CompositeError("unhandled_censored", "censored token with no censor policy", value=s) try: lim = float(s[1:]) except ValueError: raise CompositeError("bad_value", "unparseable censored token", value=s) if not math.isfinite(lim): raise CompositeError("nonfinite", "non-finite censored limit", value=s) if censor_policy == "drop": return ("missing", None) if censor_policy == "half": if s[0] != "<" or lim < 0: raise CompositeError("unsupported_half_censor", "half policy supports only half is refused") return ("num", lim / 2.0) return ("num", lim) try: f = float(s) except ValueError: raise CompositeError("bad_value", "value is neither number, missing code, nor handled censor token", value=s) if not math.isfinite(f): raise CompositeError("nonfinite", "non-finite value", value=s) return ("num", f) raise CompositeError("bad_value", "unsupported value type", value=str(type(raw))) def _validate_settings(settings): if not isinstance(settings, dict): raise CompositeError("bad_settings", "settings must be an object") allowed = {"target_length","min_coverage","residual_policy","censor_policy","missing_codes","units","boundaries","element","value_units"} required = {"target_length","min_coverage","residual_policy","censor_policy","missing_codes","units"} if set(settings)-allowed or not required.issubset(settings): raise CompositeError("settings_schema", "explicit target_length/min_coverage/residual_policy/censor_policy/missing_codes/units required; unknown fields refused") tl = settings.get("target_length") if not _finite(tl) or float(tl) <= 0: raise CompositeError("bad_target_length", "target_length must be a finite number > 0", value=repr(tl)) mc = settings.get("min_coverage", 0.0) if not _finite(mc) or not (0.0 <= float(mc) <= 1.0): raise CompositeError("bad_min_coverage", "min_coverage must be within [0,1]", value=repr(mc)) rp = settings.get("residual_policy", "keep") if rp not in VALID_RESIDUAL: raise CompositeError("bad_residual_policy", "residual_policy must be one of " + str(VALID_RESIDUAL), value=repr(rp)) cp = settings.get("censor_policy", "error") if cp not in VALID_CENSOR: raise CompositeError("bad_censor_policy", "censor_policy must be one of " + str(VALID_CENSOR), value=repr(cp)) mcodes = settings.get("missing_codes", ["", "NA"]) if not isinstance(mcodes, list) or any(not isinstance(m, str) for m in mcodes): raise CompositeError("bad_missing_codes", "missing_codes must be a list of strings") units = settings.get("units", "unit") if units not in ("m","cm","mm","ft"): raise CompositeError("bad_units", "units must be m, cm, mm or ft; no implicit conversion") for key in ("element","value_units"): if key in settings and (not isinstance(settings[key],str) or not 1<=len(settings[key])<=64): raise CompositeError("bad_label", key+" must be a short text label") braw = settings.get("boundaries", {}) if not isinstance(braw, dict): raise CompositeError("bad_boundaries", "boundaries must be an object of hole_id -> list of depths") boundaries = {} nb = 0 for hid, lst in braw.items(): if not isinstance(hid,str) or not hid or len(hid)>128: raise CompositeError("bad_boundaries", "boundary hole_id invalid") if not isinstance(lst, list): raise CompositeError("bad_boundaries", "boundaries[hole] must be a list", hole=hid) vals = [] for d in lst: if isinstance(d, bool) or not _finite(d): raise CompositeError("bad_boundaries", "boundary depths must be finite numbers", hole=hid, value=repr(d)) vals.append(float(d)); nb += 1 boundaries[hid] = vals if nb > MAX_BOUNDS: raise CompositeError("too_many_boundaries", "boundary count exceeds bound", count=nb) return dict(target_length=float(tl), min_coverage=float(mc), residual_policy=rp, censor_policy=cp, missing_codes=set(mcodes), missing_codes_list=list(mcodes), units=units, boundaries=boundaries) def _parse_assays(assays, missing_codes, censor_policy): if not isinstance(assays, list): raise CompositeError("bad_assays", "assays must be a list") if len(assays) == 0: raise CompositeError("empty_assays", "assays list is empty") if len(assays) > MAX_ROWS: raise CompositeError("too_many_rows", "assay row count exceeds bound", count=len(assays)) holes = {} for i, row in enumerate(assays): if not isinstance(row, dict): raise CompositeError("bad_row", "assay row must be an object", row=i) for k in ("hole_id", "from", "to", "value"): if k not in row: raise CompositeError("missing_field", "assay row missing field " + k, row=i, field=k) hid = row["hole_id"] if set(row) != {"hole_id","from","to","value"}: raise CompositeError("row_schema", "each assay has exactly hole_id,from,to,value",row=i) if not isinstance(hid, str) or not hid or len(hid)>128: raise CompositeError("bad_hole_id", "hole_id must be a non-empty string", row=i) a = row["from"]; b = row["to"] for name, val in (("from", a), ("to", b)): if isinstance(val, bool) or not _is_number(val): raise CompositeError("bad_depth", "depth " + name + " must be a number", row=i, field=name) if not math.isfinite(float(val)): raise CompositeError("nonfinite", "depth " + name + " is non-finite", row=i, field=name) a = float(a); b = float(b) if not math.isfinite(b-a) or not a < b: raise CompositeError("nonpositive_length", "assay row requires from < to", row=i) kind, v = _classify_value(row["value"], missing_codes, censor_policy) holes.setdefault(hid, []).append(dict(idx=i, a=a, b=b, kind=kind, v=v)) for hid, ivs in holes.items(): ivs.sort(key=lambda r: (r["a"], r["b"])) for p, q in zip(ivs, ivs[1:]): if q["a"] < p["b"]: raise CompositeError("overlap", "overlapping source intervals in hole " + hid, hole=hid) if len(holes)>MAX_HOLES: raise CompositeError("too_many_holes", "hole count exceeds bound") return holes def build_bins(lo, hi, L, boundaries, residual_policy, budget=MAX_BINS): cuts=sorted(set([lo,hi]+[float(b) for b in boundaries if lobudget+1: raise CompositeError("bin_bound", "target_length requests too many bins; increase target_length") nearest=round(ratio) n=nearest if abs(ratio-nearest)<=max(4*math.ulp(ratio),1e-14) else math.floor(ratio) if len(bins)+n>budget: raise CompositeError("bin_bound", "total bin count exceeds bound") segment=[];pos=start for i in range(n): nxt=end if i==n-1 and n==nearest and abs(ratio-nearest)<=max(4*math.ulp(ratio),1e-14) else min(end,start+(i+1)*L) if not posbudget:raise CompositeError("bin_bound", "total bin count exceeds bound") return bins def _bounded(payload): stack=[(payload,0)]; nodes=0; byte_count=0 while stack: value,depth=stack.pop();nodes+=1 if nodes>MAX_NODES or depth>MAX_DEPTH: raise CompositeError("input_bound", "input node/depth bound exceeded") if type(value) is dict: if len(value)>MAX_ROWS:raise CompositeError("input_bound", "object size exceeded") for k,v in value.items(): if not isinstance(k,str):raise CompositeError("bad_key", "object keys must be strings") stack.extend([(k,depth+1),(v,depth+1)]) elif type(value) is list: if len(value)>MAX_ROWS:raise CompositeError("input_bound", "array size exceeded") stack.extend((v,depth+1) for v in value) elif isinstance(value,str): if len(value)>MAX_STRING or any(ord(c)<32 and c not in "\t\r\n" for c in value): raise CompositeError("string_bound", "strings exceed length bound or contain control characters") byte_count+=len(value.encode('utf-8')) elif type(value) in (int,float): if not _finite(value):raise CompositeError("nonfinite", "all numeric input must be finite and representable") byte_count+=32 elif value is None or type(value) is bool:byte_count+=8 else:raise CompositeError("bad_type", "unsupported input type") if byte_count>MAX_BYTES:raise CompositeError("input_bound", "input byte bound exceeded") if len(_canon(payload).encode())>MAX_BYTES:raise CompositeError("input_bound", "input byte bound exceeded") def _sum(values): try:value=math.fsum(values) except (OverflowError,ValueError):raise CompositeError("arithmetic_range", "arithmetic exceeds finite supported range") if not math.isfinite(value):raise CompositeError("arithmetic_range", "arithmetic exceeds finite supported range") return value def _canon(payload): return json.dumps(payload, sort_keys=True, separators=(",", ":"), allow_nan=False) def _failure(error): return {"status":"FAIL","summary":{"status":"FAIL","error_code":error.code}, "tables":{k:[] for k in CSV_FILES},"findings":[dict(level="error",code=error.code,message=error.message,**error.ctx)], "provenance":{"version":VERSION,"algorithm":ALGORITHM,"scope":SCOPE}} def run(payload): try: _bounded(payload) if not isinstance(payload,dict) or set(payload)-{"assays","settings","_note"}: raise CompositeError("bad_payload","payload must contain assays/settings and optional synthetic _note only") if "_note" in payload and not isinstance(payload["_note"],str):raise CompositeError("bad_note","_note must be text") S=_validate_settings(payload.get("settings",{})) holes=_parse_assays(payload.get("assays"),S["missing_codes"],S["censor_policy"]) if set(S['boundaries'])-set(holes):raise CompositeError("unknown_boundary_hole","boundaries reference an absent hole") comp=[];contrib=[];coverage=[];excluded=[];input_terms=[];output_terms=[];excluded_terms=[] unknown=False;gaps=0;all_bins=0;overlap_steps=0 for hid in sorted(holes): ivs=holes[hid] for left,right in zip(ivs,ivs[1:]): if left['b']MAX_CONTRIBUTORS:raise CompositeError("work_bound","overlap/contributor bound exceeded") start=max(c,iv['a']);end=min(d,iv['b']);w=end-start if w<=0:continue assigned[iv['idx']].append((start,end)) if iv['kind']=='num': term=w*iv['v'];_sum([term]);parts.append(term);weights.append(w);used.append((iv,w,term)) den=_sum(weights);num=_sum(parts);length=d-c;cov=den/length if cov>1 and not math.isclose(cov,1,rel_tol=1e-12):raise CompositeError("coverage_range","coverage exceeds one") cov=min(1.0,cov) if denpos: length=start-pos;excluded_terms.append(length*iv['v']) excluded.append(dict(hole_id=hid,source_row=iv['idx'],**{'from':pos,'to':start},excluded_length=length,value=iv['v'],reason="declared_residual_drop")) pos=end integral_in=_sum(input_terms);integral_out=_sum(output_terms);integral_excluded=_sum(excluded_terms) residual=_sum([integral_in,-integral_out,-integral_excluded]) status='UNKNOWN' if unknown else 'PASS' findings=[] if unknown:findings.append(dict(level='info',code='partial_observations',message='Missing/censored-dropped values or source gaps remain UNKNOWN; tables contain observed-only values, never zero-filled.')) low=sum(row['low_coverage'] for row in comp) if low:findings.append(dict(level='warn',code='low_coverage',count=low,message='Observed-only means below the declared coverage threshold are retained and flagged.')) if not comp:findings.append(dict(level='info',code='no_composites',message='No numeric composite remains under the declared policies; inspect coverage and exclusions.')) if S['censor_policy'] in ('half','limit'):findings.append(dict(level='info',code='declared_censor_substitution',message='Censored values use the explicitly named substitution policy; substitutes are not measured values.')) summary=dict(status=status,holes=len(holes),source_intervals=sum(map(len,holes.values())),composites=len(comp),bins=all_bins,excluded_rows=len(excluded),gaps=gaps,overlap_steps=overlap_steps, integral_in=integral_in,integral_out=integral_out,integral_excluded=integral_excluded,conservation_residual=residual,units=S['units'],target_length=S['target_length']) policy=dict(payload['settings']);policy.setdefault('boundaries',{}) result=dict(status=status,summary=summary,tables={'composites.csv':comp,'contributors.csv':contrib,'coverage.csv':coverage,'excluded-intervals.csv':excluded},findings=findings, provenance=dict(version=VERSION,algorithm=ALGORITHM,scope=SCOPE,input_sha256=hashlib.sha256(_canon(payload).encode()).hexdigest(),settings=policy, limits=dict(input_bytes=MAX_BYTES,rows=MAX_ROWS,holes=MAX_HOLES,bins=MAX_BINS,overlaps=MAX_CONTRIBUTORS,boundaries=MAX_BOUNDS,depth=MAX_DEPTH,string_chars=MAX_STRING))) _canon(result) return result except CompositeError as e:return _failure(e) except (ValueError,TypeError,OverflowError,RecursionError,UnicodeError): return _failure(CompositeError('invalid_input','Input types, text or numeric range exceed the supported schema')) def _neutralize(x): if isinstance(x, bool): return "true" if x else "false" if isinstance(x, str) and x.lstrip()[:1] in ("=", "+", "-", "@") or (isinstance(x,str) and x[:1] in ("\t","\r","\n")): return "'" + x return x def _csv_bytes(name, rows): cols = COLUMNS[name] out = io.StringIO() w = csv.writer(out, lineterminator="\n") w.writerow(cols) for r in rows: w.writerow([_neutralize(r.get(c, "")) for c in cols]) return out.getvalue().encode("utf-8") VIEWER_CSS = '/* ==========================================================================\n Dated change feeds — aligned to the ustechautomations.com design system.\n Tokens, type scale, radius and accent are lifted from the live main site.\n Take them from assets/WebsiteStyleProvider-*.css, NOT assets/root-*.css: the\n root sheet is the app\'s palette and the website overrides it. Reading the\n wrong one is how these pages ended up with a near-black button where the\n marketing site has a blue one.\n\n Look only. Prices, sample rows, event ids and honesty lines live in the\n HTML and are frozen: never restyle a fact out of existence.\n Each family page sets data-family on . Nothing in this file reads it:\n there is one accent and every family shares it. The attribute is kept for\n the page\'s own scripts and for anyone grepping the built site by family.\n ========================================================================== */\n\n:root {\n /* type — same stack the main site resolves --font-sans to */\n --sans: "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n --serif: "PT Serif", ui-serif, Georgia, "Times New Roman", serif;\n --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;\n\n /* main-site tokens, light */\n --background: 220 10% 99%;\n --foreground: 220 20% 10%;\n --card: 0 0% 100%;\n --card-foreground: 220 20% 10%;\n --secondary: 220 12% 97%;\n --muted: 220 12% 97%;\n --muted-foreground: 220 10% 42%;\n --border: 220 13% 94%;\n --primary: 207 100% 50%;\n --primary-foreground: 0 0% 100%;\n --primary-hover: 207 100% 44%;\n --accent-blue: 207 100% 50%;\n --accent-emerald: 149 80% 90%;\n --accent-emerald-fg: 161 94% 30%;\n --accent-amber: 48 96% 89%;\n --accent-amber-fg: 26 90% 37%;\n --radius: .5rem;\n --shadow-color: 220 15% 60%;\n\n /* resolved */\n --bg: hsl(var(--background));\n --surface: hsl(var(--card));\n --surface-2: hsl(var(--secondary));\n --fg: hsl(var(--foreground));\n --muted-fg: hsl(var(--muted-foreground));\n --faint: hsl(var(--muted-foreground) / .78);\n --line: hsl(var(--border));\n --line-strong: hsl(var(--border) / 1.6);\n --accent: hsl(var(--accent-blue));\n --shadow-sm: 0 1px 2px hsl(var(--shadow-color) / .08);\n --shadow-md: 0 4px 16px -4px hsl(var(--shadow-color) / .16);\n}\n\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n --background: 220 15% 8%;\n --foreground: 220 15% 96%;\n --card: 220 12% 10%;\n --card-foreground: 220 15% 96%;\n --secondary: 220 10% 16%;\n --muted: 220 10% 16%;\n --muted-foreground: 220 8% 62%;\n --border: 220 10% 18%;\n --primary: 207 100% 50%;\n --primary-foreground: 0 0% 100%;\n --primary-hover: 207 100% 44%;\n --accent-blue: 207 100% 60%;\n --accent-emerald: 164 86% 16%;\n --accent-emerald-fg: 158 64% 52%;\n --accent-amber: 22 78% 26%;\n --accent-amber-fg: 45.9 96.7% 64.5%;\n --shadow-color: 220 20% 4%;\n }\n}\n:root[data-theme="dark"] {\n --background: 220 15% 8%;\n --foreground: 220 15% 96%;\n --card: 220 12% 10%;\n --card-foreground: 220 15% 96%;\n --secondary: 220 10% 16%;\n --muted: 220 10% 16%;\n --muted-foreground: 220 8% 62%;\n --border: 220 10% 18%;\n --primary: 207 100% 50%;\n --primary-foreground: 0 0% 100%;\n --primary-hover: 207 100% 44%;\n --accent-blue: 207 100% 60%;\n --accent-emerald: 164 86% 16%;\n --accent-emerald-fg: 158 64% 52%;\n --accent-amber: 22 78% 26%;\n --accent-amber-fg: 45.9 96.7% 64.5%;\n --shadow-color: 220 20% 4%;\n}\n\n*, *::before, *::after { box-sizing: border-box; }\n\nhtml { -webkit-text-size-adjust: 100%; background: hsl(var(--background)); }\n\nbody {\n margin: 0;\n background: var(--bg);\n color: var(--fg);\n font-family: var(--sans);\n font-size: 16px;\n font-weight: 500;\n line-height: 1.65;\n -webkit-font-smoothing: antialiased;\n text-rendering: optimizeLegibility;\n}\n\n.wrap { width: 100%; max-width: 1280px; margin: 0 auto; padding: 0 1.5rem; }\n@media (min-width: 768px) { .wrap { padding: 0 2rem; } }\n\na { color: var(--accent); text-decoration: none; }\na:hover { text-decoration: underline; }\n\n.skip {\n position: absolute; left: -9999px; top: 0;\n background: var(--surface); color: var(--fg);\n padding: .75rem 1rem; border: 1px solid var(--line);\n border-radius: var(--radius); z-index: 100;\n}\n.skip:focus { left: 1rem; top: 1rem; }\n\n/* ---------- masthead: mirrors the main-site sticky header ---------- */\n.masthead {\n position: sticky; top: 0; z-index: 40;\n width: 100%;\n border-bottom: 1px solid var(--line);\n background: hsl(var(--background) / .8);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n}\n.masthead .wrap {\n display: flex; align-items: center; gap: 1.25rem;\n min-height: 64px; flex-wrap: wrap;\n}\n@media (min-width: 1024px) { .masthead .wrap { flex-wrap: nowrap; } }\n.wordmark {\n display: inline-flex; align-items: center; gap: .5rem;\n font-weight: 900; font-size: 1rem; letter-spacing: normal;\n text-transform: uppercase;\n color: var(--fg); text-decoration: none; white-space: nowrap;\n}\n@media (min-width: 640px) { .wordmark { font-size: 1.25rem; letter-spacing: .025em; } }\n.usta-logo { width: 24px; height: 24px; display: block; flex: none; }\n.wordmark:hover { text-decoration: none; opacity: .8; }\n.wordmark span { font-weight: 500; color: var(--muted-fg); }\n\n.mast-nav { display: none; gap: 2rem; margin-left: 2rem; align-items: center; flex: 1; }\n/* main site keeps the links beside the wordmark and the CTA hard right */\n.mast-cta { margin-left: auto; }\n@media (min-width: 1024px) { .mast-nav { display: flex; } }\n.mast-nav a {\n font-size: .875rem; font-weight: 500; color: var(--fg); text-decoration: none;\n}\n.mast-nav a:hover { color: hsl(var(--primary)); text-decoration: none; }\n.mast-cta {\n display: inline-flex; align-items: center;\n background: hsl(var(--primary)); color: hsl(var(--primary-foreground));\n font-size: .875rem; font-weight: 600;\n padding: .5rem 1rem; border-radius: var(--radius);\n text-decoration: none; white-space: nowrap;\n}\n.mast-cta:hover { background: hsl(var(--primary-hover)); text-decoration: none; }\n\n.crumbs {\n width: 100%; margin: 0 0 .75rem; font-size: .8125rem; color: var(--muted-fg);\n}\n.crumbbar { border-bottom: 1px solid var(--line); background: hsl(var(--background)); }\n.crumbbar .crumbs {\n width: auto; margin: 0; padding: .625rem 0;\n white-space: nowrap; overflow-x: auto;\n}\n.crumbs a { color: var(--muted-fg); }\n.crumbs .sep { padding: 0 .5rem; opacity: .5; }\n\n/* ---------- hero ---------- */\n.hero { padding: 3.5rem 0 2rem; }\n.hero h1 {\n font-size: 3rem;\n line-height: 1.15; letter-spacing: -.025em; font-weight: 500;\n margin: 0 0 1rem; max-width: 20ch;\n}\n@media (min-width: 768px) { .hero h1 { font-size: 3.75rem; } }\n@media (min-width: 1024px) { .hero h1 { font-size: 4.5rem; letter-spacing: -.03em; } }\n.eyebrow {\n display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;\n margin: 0 0 1rem;\n font-size: .8125rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;\n color: var(--muted-fg);\n}\n.dot { width: 3px; height: 3px; border-radius: 999px; background: currentColor; opacity: .55; display: inline-block; }\n.lede {\n font-size: clamp(1.0625rem, 1rem + .35vw, 1.25rem);\n line-height: 1.6; color: var(--muted-fg); max-width: 68ch; margin: 0 0 2rem;\n}\n.lede strong { color: var(--fg); font-weight: 600; }\n\n/* ---------- fact rail ---------- */\n.rail {\n display: grid; gap: 1px; margin: 0;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n background: var(--line);\n border: 1px solid var(--line);\n border-radius: var(--radius);\n overflow: hidden;\n}\n.rail > div { background: var(--surface); padding: 1rem 1.25rem; }\n.rail dt {\n font-size: .75rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;\n color: var(--muted-fg); margin: 0 0 .375rem;\n}\n.rail dd { margin: 0; font-size: .9375rem; font-weight: 500; }\n.rail dd.price, .amount {\n font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em;\n font-variant-numeric: tabular-nums;\n}\n\n/* ---------- main ---------- */\nmain { padding: 1rem 0 4rem; }\nmain section { margin: 0 0 2.75rem; max-width: 76ch; }\n/* Evidence tables use the full 1280px container the main site\'s sections use,\n while the prose around them keeps its reading measure. */\nmain section:has(.evidence) { max-width: none; }\nmain section:has(.evidence) > p,\nmain section:has(.evidence) > h2,\nmain section:has(.evidence) > h3 { max-width: 76ch; }\n/* Main-site heading character (weight/tracking/leading are its h1-h6 rule).\n Sizes step one rung down its ladder: a feed page\'s h2 is a subsection of a\n record, not a marketing section header, so it takes the site\'s h3 numbers. */\nh2 {\n font-size: 1.875rem; font-weight: 500; letter-spacing: -.025em; line-height: 1.15;\n margin: 0 0 .875rem;\n}\nh3 {\n font-size: 1.5rem; font-weight: 500; letter-spacing: -.025em; line-height: 1.15;\n margin: 0 0 .5rem;\n}\n@media (min-width: 768px) {\n h2 { font-size: 2.25rem; }\n h3 { font-size: 1.875rem; }\n}\np { margin: 0 0 1rem; line-height: 1.625; }\nmain p { color: hsl(var(--foreground) / .86); }\nstrong { font-weight: 650; color: var(--fg); }\n\n/* ---------- pills ---------- */\n.pill {\n display: inline-flex; align-items: center; gap: .375rem;\n font-size: .75rem; font-weight: 650; letter-spacing: .01em;\n padding: .25rem .625rem; border-radius: 999px;\n border: 1px solid transparent; white-space: nowrap;\n}\n.pill-hold {\n background: hsl(var(--accent-amber)); color: hsl(var(--accent-amber-fg));\n border-color: hsl(var(--accent-amber-fg) / .22);\n}\n.pill-ready {\n background: hsl(var(--accent-emerald)); color: hsl(var(--accent-emerald-fg));\n border-color: hsl(var(--accent-emerald-fg) / .22);\n}\n\n/* ---------- honesty panel ---------- */\n.honest {\n border: 1px solid hsl(var(--accent-amber-fg) / .3);\n background: hsl(var(--accent-amber) / .5);\n border-radius: var(--radius);\n padding: 1.125rem 1.25rem;\n}\n.honest p:last-child { margin-bottom: 0; }\n.honest strong { color: hsl(var(--accent-amber-fg)); }\n\n/* The same disclosure, sitting in a hero rather than in the body. Five family\n pages used this class with nothing defined for it, so their "not for sale\n yet" line rendered as ordinary body text while the identical sentence on\n dc-buildout got a panel. One shop, one look. */\n.hero-note {\n border: 1px solid hsl(var(--accent-amber-fg) / .3);\n background: hsl(var(--accent-amber) / .5);\n border-radius: var(--radius);\n padding: 1rem 1.125rem;\n margin: 0 0 1.25rem;\n max-width: 62ch;\n}\n.hero-note strong { color: hsl(var(--accent-amber-fg)); }\n\n/* ---------- spec list ---------- */\n.spec { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .75rem; }\n.spec li {\n display: grid; gap: .125rem;\n border-left: 2px solid var(--line-strong);\n padding: .125rem 0 .125rem 1rem;\n}\n.spec li strong { font-weight: 650; }\n.sub { color: var(--muted-fg); font-size: .9375rem; }\n\n/* ---------- cards (hub) ---------- */\n.cards { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }\n.hub-groups { display: grid; gap: 2.5rem; }\n.group { max-width: none; }\n\n/* The list of a feed\'s own pages, printed on the feed\'s page. Columns, not one\n long line: twenty-seven states stacked vertically is a wall, and a reader\n scanning for one name reads across a column far faster than down a list.\n break-inside keeps a name from being split over a column boundary. */\n.slice-index { margin-top: 2.75rem; border-top: 1px solid var(--line); padding-top: 1.75rem; }\n.slice-index h2 { margin-bottom: .9rem; }\n.slice-list { columns: 3 190px; column-gap: 1.75rem; list-style: none; padding: 0; margin: 0 0 .9rem; }\n.slice-list li { break-inside: avoid; margin: 0 0 .5rem; }\n.slice-list a { text-decoration: none; }\n.slice-list a:hover { text-decoration: underline; }\n.card {\n display: block; background: var(--surface);\n border: 1px solid var(--line); border-radius: var(--radius);\n padding: 1.25rem; color: inherit; text-decoration: none;\n box-shadow: var(--shadow-sm);\n transition: box-shadow .15s ease, border-color .15s ease, transform .15s ease;\n}\na.card:hover {\n text-decoration: none; border-color: hsl(var(--accent-blue) / .5);\n box-shadow: var(--shadow-md); transform: translateY(-1px);\n}\n.card h3 { margin: 0 0 .375rem; }\n.card .who { color: var(--muted-fg); font-size: .875rem; margin: 0 0 .875rem; }\n.card .meta { display: flex; align-items: center; gap: .625rem; flex-wrap: wrap; font-size: .8125rem; color: var(--muted-fg); }\n\n/* ---------- evidence / sample panels ---------- */\n.evidence {\n border: 1px solid var(--line); border-radius: var(--radius);\n overflow: hidden; background: var(--surface); box-shadow: var(--shadow-sm);\n}\n.evidence-head {\n display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;\n padding: .75rem 1.125rem; background: var(--surface-2);\n border-bottom: 1px solid var(--line);\n font-size: .8125rem; font-weight: 600; color: var(--muted-fg);\n}\n.evidence-body { padding: 1.125rem; }\n.blank { color: var(--muted-fg); font-style: italic; }\n.scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }\n\ntable { width: 100%; border-collapse: collapse; font-size: .875rem; }\nth, td { text-align: left; padding: .625rem .75rem; border-bottom: 1px solid var(--line); }\nth {\n font-size: .6875rem; font-weight: 650; letter-spacing: .05em; text-transform: uppercase;\n color: var(--muted-fg);\n}\ntd.num, .num { font-variant-numeric: tabular-nums; }\ntbody tr:last-child td { border-bottom: 0; }\n\n.stamp, .seal, .fact, .change, .moved {\n font-family: var(--mono); font-size: .8125rem;\n}\nh1 > .seal, h1 > .stamp, h2 > .seal, h2 > .stamp, h3 > .seal, h3 > .stamp {\n display: block; margin-top: .375rem;\n font-weight: 400; letter-spacing: 0; color: var(--muted-fg);\n font-size: .8125rem; line-height: 1.5;\n}\n.seal { color: var(--muted-fg); word-break: break-all; }\n.stamp { color: var(--muted-fg); }\n.note { font-size: .875rem; color: var(--muted-fg); }\n\n.steps { display: grid; gap: 1rem; padding: 0; margin: 0 0 1rem; list-style: none; counter-reset: step; }\n.steps li { display: grid; grid-template-columns: auto 1fr; gap: .875rem; align-items: start; }\n\n/* ---------- contact ---------- */\n.contact {\n border: 1px solid var(--line); border-radius: var(--radius);\n background: var(--surface); padding: 1.75rem; box-shadow: var(--shadow-sm);\n max-width: none;\n}\n.contact h2 { margin-top: 0; }\n.mail {\n display: inline-flex; align-items: center;\n background: hsl(var(--primary)); color: hsl(var(--primary-foreground));\n font-weight: 600; font-size: .9375rem;\n padding: .625rem 1.25rem; border-radius: var(--radius); text-decoration: none;\n}\n.mail:hover { background: hsl(var(--primary-hover)); text-decoration: none; }\n.mail-note { margin: .875rem 0 0; font-size: .8125rem; color: var(--muted-fg); }\n\n/* ---------- footer: mirrors the main-site footer ---------- */\nfooter.site {\n border-top: 1px solid var(--line);\n background: var(--bg);\n padding: 4rem 0 2rem;\n font-size: .875rem;\n}\n@media (min-width: 768px) { footer.site { padding: 5rem 0 2rem; } }\n.foot-grid {\n display: grid; gap: 3rem; margin-bottom: 3rem;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n}\n.foot-brand { grid-column: 1 / -1; }\n@media (min-width: 1024px) { .foot-brand { grid-column: span 2; max-width: 320px; } }\n.foot-brand .wordmark {\n font-size: 1.125rem; font-weight: 600; letter-spacing: -.025em; text-transform: none;\n}\n.foot-brand p { color: var(--muted-fg); margin: .75rem 0 1rem; }\n.foot-col h4 {\n font-size: 1.875rem; font-weight: 500; letter-spacing: -.025em; line-height: 1.15;\n color: var(--fg); margin: 0 0 1rem;\n}\n@media (min-width: 768px) { .foot-col h4 { font-size: 2.25rem; } }\n.foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .75rem; }\n.foot-col a { color: var(--muted-fg); }\n.foot-col a:hover { color: hsl(var(--primary)); }\n.foot-bottom {\n border-top: 1px solid var(--line); padding-top: 1.5rem;\n display: grid; gap: .75rem; color: var(--muted-fg);\n}\nfooter.site p { color: var(--muted-fg); }\nfooter.site .addr { font-size: .8125rem; }\n.foot-honest { max-width: 76ch; }\n\n/* ---------- offer: the pay path ----------\n A page shows btn-buy only when catalog.json carries a checkout that was\n fetched and found working. btn-ghost is the email fallback. Both are the\n same shape so a page does not look broken when the pay link is missing. */\n.hero-cta {\n display: flex; flex-wrap: wrap; align-items: center; gap: .875rem;\n margin: 1.5rem 0 0;\n}\n.btn {\n display: inline-flex; align-items: center; justify-content: center;\n font-weight: 650; font-size: .9375rem; line-height: 1;\n padding: .75rem 1.375rem; border-radius: var(--radius);\n text-decoration: none; border: 1px solid transparent;\n transition: background .15s ease, border-color .15s ease;\n}\n.btn:hover { text-decoration: none; }\n.btn-buy {\n background: hsl(var(--primary)); color: hsl(var(--primary-foreground));\n box-shadow: 0 1px 2px hsl(var(--foreground) / .08);\n}\n.btn-buy:hover { background: hsl(var(--primary-hover)); }\n.btn-ghost {\n background: transparent; color: hsl(var(--primary));\n border-color: hsl(var(--primary) / .35);\n}\n.btn-ghost:hover { background: hsl(var(--primary) / .06); border-color: hsl(var(--primary) / .55); }\n.btn-lg { padding: .9375rem 1.75rem; font-size: 1rem; }\n.btn-note { font-size: .8125rem; color: var(--muted-fg); }\n.contact.buy .buy-price {\n margin: 0 0 1.125rem; font-size: 1.125rem; color: var(--fg);\n}\n.contact.buy .buy-price strong { font-size: 1.5rem; letter-spacing: -.01em; }\n.contact.buy .btn-lg { margin-bottom: .25rem; }\n@media (max-width: 34rem) {\n .hero-cta { flex-direction: column; align-items: flex-start; }\n .btn { width: 100%; }\n}\n\nbody[data-family="corecomposite"] svg { max-width:100%; height:auto; }\nbody[data-family="corecomposite"] .core-strip { fill:var(--accent);stroke:var(--fg);stroke-width:1; }\n' VIEWER_CSS += '\nbody[data-family="corecomposite"] h2 {overflow-wrap:anywhere;}\n' README_TXT = ("CoreComposite result package\n" + "version: " + VERSION + "\n" + "algorithm: " + ALGORITHM + "\n\nSCOPE\n" + SCOPE + "\n\nFILES\n" + "composites.csv - one row per target bin with a usable value.\n" + "contributors.csv - exact source-row lineage and weights per composite.\n" + "coverage.csv - covered length and coverage fraction for every bin.\n" + "excluded-intervals.csv - lengths/values not carried into any composite.\n" + "input.json - the exact payload, policy.json - applied policies.\n" + "source-hashes.json / manifest.json - SHA256 lineage of every file.\n" + "viewer.html - static hole-strip viewer (no network).\n\n" + "coverage = contributing length / bin length. Missing values are excluded, not zero-filled.\n") def _viewer_html(result): # User text is escaped into static text nodes; there is no executable data. rows=result['tables']['composites.csv']; sections=[] for hid in sorted(set(r['hole_id'] for r in result['tables']['coverage.csv'])): bins=[r for r in result['tables']['coverage.csv'] if r['hole_id']==hid] low=min(r['from'] for r in bins);high=max(r['to'] for r in bins);span=high-low bars=[] for row in bins: x=10+780*((row['from']-low)/span);width=780*(row['length']/span) label=html.escape(f"{row['from']:g} to {row['to']:g}; coverage {row['coverage']:.6g}",quote=True) bars.append(f'{label}') sections.append('

'+html.escape(hid)+'

'+''.join(bars)+'

Depth '+html.escape(f'{low:g} to {high:g}')+' '+html.escape(result['summary']['units'])+'. Each outlined segment is a target bin; text tables carry the exact observed coverage.

') table=''.join(''+''.join(''+html.escape(str(r[k]))+'' for k in ['hole_id','from','to','composite_value','coverage'])+'' for r in rows) return ('' '' 'CoreComposite — offline interval evidence' '
US Tech Automations / CoreComposite
' '

Offline calculation evidence

CoreComposite interval evidence

'+html.escape(result['status'])+' — observed-length means and exact contributor lineage.

System font fallback is used when Satoshi is unavailable offline.

Open composite table
' '
'+''.join(sections)+'

Observed values

'+table+'
HoleFromToObserved meanCoverage

'+html.escape(SCOPE)+'

' '') def bundle(payload): result = run(payload) if result["status"] == "FAIL": raise CompositeError("refuse_bundle", "cannot bundle invalid input") entries = [] entries.append(("report.json", json.dumps(result, sort_keys=True, indent=2, allow_nan=False).encode("utf-8"))) for name in CSV_FILES: entries.append((name, _csv_bytes(name, result["tables"][name]))) entries.append(("input.json", json.dumps(payload, sort_keys=True, indent=2, allow_nan=False).encode("utf-8"))) entries.append(("policy.json", json.dumps(result["provenance"]["settings"], sort_keys=True, indent=2).encode("utf-8"))) entries.append(("README.txt", README_TXT.encode("utf-8"))) entries.append(("viewer.html", _viewer_html(result).encode("utf-8"))) entries.append(("styles.css", VIEWER_CSS.encode("utf-8"))) src = {n: hashlib.sha256(b).hexdigest() for n, b in entries} entries.append(("source-hashes.json", json.dumps(src, sort_keys=True, indent=2).encode("utf-8"))) manifest = {"version": VERSION, "status": result["status"], "files": {n: hashlib.sha256(b).hexdigest() for n, b in entries}} entries.append(("manifest.json", json.dumps(manifest, sort_keys=True, indent=2).encode("utf-8"))) buf = io.BytesIO() with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as z: for name, b in sorted(entries): zi = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0)) zi.external_attr = 0o644 << 16 zi.compress_type = zipfile.ZIP_DEFLATED z.writestr(zi, b) return buf.getvalue() def _strict_json(text): try: size=len(text.encode('utf-8')) if isinstance(text,str) else MAX_BYTES+1 except UnicodeError: raise CompositeError('bad_json','JSON contains invalid Unicode') if size>MAX_BYTES: raise CompositeError('json_bound','JSON must be text within the input byte bound') def pairs(items): out={} for k,v in items: if k in out:raise CompositeError('duplicate_json_key','Duplicate JSON keys are refused') out[k]=v return out def nonfinite(value):raise CompositeError('nonfinite','Non-finite JSON constants are refused') try: payload=json.loads(text,object_pairs_hook=pairs,parse_constant=nonfinite) _bounded(payload) return payload except CompositeError:raise except (ValueError,TypeError,RecursionError,UnicodeError,OverflowError):raise CompositeError('bad_json','Malformed or excessively nested JSON') def run_json(text): try:result=run(_strict_json(text)) except CompositeError as e:result=_failure(e) return json.dumps(result,allow_nan=False,sort_keys=True) def _decode_file(obj): if not isinstance(obj, dict) or set(obj)!={"encoding","content"}: raise CompositeError("bad_file", "each file must be {encoding, content}") enc = obj.get("encoding", "utf8"); content = obj["content"] if not isinstance(content, str) or len(content.encode("utf-8"))>MAX_BYTES: raise CompositeError("bad_file", "file content must be a string") if enc == "utf8": return content if enc == "base64": try: return base64.b64decode(content, validate=True).decode("utf-8") except Exception: raise CompositeError("bad_base64", "invalid base64 file content") raise CompositeError("bad_encoding", "unsupported encoding " + str(enc)) def _num_or_str(s): try: f = float(s) if math.isfinite(f): return f except ValueError: pass return s def _assays_from_csv(text): try: rdr=csv.reader(io.StringIO(text),strict=True);header=next(rdr) if header!=['hole_id','from','to','value']: raise CompositeError('bad_csv_header','assays.csv header must be exactly hole_id,from,to,value') rows=[] for line,r in enumerate(rdr,2): if len(r)!=4:raise CompositeError('ragged_csv','Every CSV row requires exactly four fields',line=line) if len(rows)>=MAX_ROWS:raise CompositeError('row_bound','CSV row bound exceeded') if any(len(v)>MAX_STRING for v in r):raise CompositeError('string_bound','CSV field exceeds character bound') try:a=float(r[1]);b=float(r[2]) except ValueError:raise CompositeError('bad_csv_number','from/to must be finite numeric depths',line=line) rows.append({'hole_id':r[0],'from':a,'to':b,'value':r[3].strip()}) return rows except (csv.Error,StopIteration):raise CompositeError('bad_csv','Malformed or empty CSV') def files_to_payload(files): if not isinstance(files,dict) or not files or len(files)>3: raise CompositeError('bad_files','Provide input.json alone, or assays.csv and settings.json') if any(not isinstance(n,str) or '/' in n or '\\' in n or n.startswith('.') for n in files): raise CompositeError('bad_filename','Only documented plain basenames are accepted') if set(files)=={'input.json'}:return _strict_json(_decode_file(files['input.json'])) if set(files) not in (set(CORE_FILES),set(CORE_FILES)|{'boundaries.csv'}):raise CompositeError('unexpected_files','Provide input.json alone, or assays.csv/settings.json with optional boundaries.csv') text=_decode_file(files['assays.csv']);settings_text=_decode_file(files['settings.json']) if len(text.encode())+len(settings_text.encode())>MAX_BYTES:raise CompositeError('input_bound','Combined file bytes exceed bound') parsed_settings=_strict_json(settings_text) if not isinstance(parsed_settings,dict):raise CompositeError('bad_settings','settings.json must contain an object') payload={'assays':_assays_from_csv(text),'settings':parsed_settings} if 'boundaries.csv' in files: if payload['settings'].get('boundaries'): raise CompositeError('ambiguous_boundaries','Use settings boundaries or boundaries.csv, not both') text_b=_decode_file(files['boundaries.csv']) if len(text.encode())+len(settings_text.encode())+len(text_b.encode())>MAX_BYTES:raise CompositeError('input_bound','Combined files exceed byte bound') try: rows=csv.reader(io.StringIO(text_b),strict=True) if next(rows)!=['hole_id','depth']:raise CompositeError('bad_boundary_header','boundaries.csv header must be hole_id,depth') boundaries={} for i,row in enumerate(rows): if i>=MAX_BOUNDS or len(row)!=2:raise CompositeError('bad_boundary_csv','Boundary row count or column count invalid') try:depth=float(row[1]) except ValueError:raise CompositeError('bad_boundary_depth','Boundary depth must be finite numeric') boundaries.setdefault(row[0],[]).append(depth) payload['settings']['boundaries']=boundaries except (csv.Error,StopIteration):raise CompositeError('bad_boundary_csv','Malformed boundary CSV') _bounded(payload) return payload def demo(): return {"_note": "synthetic demo sample, not real assay data", "assays": [{"hole_id": "DEMO1", "from": 0.0, "to": 1.0, "value": 2.0}, {"hole_id": "DEMO1", "from": 1.0, "to": 3.0, "value": 5.0}], "settings": {"units": "m", "target_length": 3.0, "min_coverage": 0.5, "residual_policy": "keep", "missing_codes": ["", "NA"], "censor_policy": "error", "boundaries": {}}} def _atomic_write(path, data): d = os.path.dirname(os.path.abspath(path)) fd, tmp = tempfile.mkstemp(dir=d) try: with os.fdopen(fd, "wb") as f: f.write(data) os.replace(tmp, path) except Exception: try: os.unlink(tmp) except OSError: pass raise def _main(argv): if len(argv)!=3: sys.stderr.write('usage: python3 product.py INPUT.json OUTPUT_DIR\n') return 2 try: with open(argv[1],'rb') as f:raw=f.read(MAX_BYTES+1) if len(raw)>MAX_BYTES:raise CompositeError('input_bound','Input file exceeds byte bound') payload=_strict_json(raw.decode('utf-8'));result=run(payload) except (CompositeError,OSError,UnicodeError) as e: result=_failure(e if isinstance(e,CompositeError) else CompositeError('input_unreadable','Input could not be read as UTF-8 JSON')) payload=None try: outdir=os.path.abspath(argv[2]) if os.path.realpath(outdir)!=outdir:raise OSError('output directory symlink refused') os.makedirs(outdir,exist_ok=True) for name in ('report.json','result.zip'): if os.path.islink(os.path.join(outdir,name)):raise OSError('output symlink refused') _atomic_write(os.path.join(outdir,'report.json'),json.dumps(result,indent=2,allow_nan=False,sort_keys=True).encode()) if result['status']!='FAIL':_atomic_write(os.path.join(outdir,'result.zip'),bundle(payload)) else: old=os.path.join(outdir,'result.zip') if os.path.isfile(old):os.unlink(old) except (OSError,CompositeError): sys.stderr.write('Output could not be written safely.\n');return 2 return {'PASS':0,'FAIL':2,'UNKNOWN':3}[result['status']] if __name__ == "__main__": sys.exit(_main(sys.argv))