Audit Specs¶
AuditSpec is a serializable configuration object for standard
updatesupport audits. Use it when an audit should be reproducible, checked
into a model-review folder, generated by another system, or rerun in CI.
import updatesupport as us
spec = us.AuditSpec(
kind="public_descent",
public=["AGE_BAND", "SEX"],
hidden=["AGE_BAND", "SEX", "OCC_MAJOR", "WKHP_BAND"],
target="income_over_threshold",
weight="sample_weight",
candidate_refinements=["OCC_MAJOR", "WKHP_BAND"],
q={"name": "bounded_shift", "radius": 0.5},
min_cell_weight=25,
title="Income-Threshold Representation Audit",
)
run = spec.run(rows_or_frame)
print(run.to_markdown())
print(run.to_json())
print(run.to_tables().keys())
The executed AuditRun keeps both the spec and report:
payload = run.as_dict()
payload["spec"]
payload["report"]
Supported Kinds¶
Use kind="public_descent" for the standard report:
spec = us.AuditSpec(
kind="public_descent",
public=["segment"],
hidden=["segment", "region", "tenure_band"],
target="outcome_rate",
q="saturated",
)
Use kind="sensitivity" for robustness grids:
spec = us.AuditSpec(
kind="sensitivity",
public=["segment"],
hidden=["segment", "region", "tenure_band"],
target="outcome_rate",
q_presets=[
"saturated",
{"name": "bounded_shift", "radius": 0.5},
"observed",
],
min_cell_weights=[1, 10, 25],
)
Use kind="frontier" for public-representation search:
spec = us.AuditSpec(
kind="frontier",
public=["segment"],
hidden=["segment", "region", "tenure_band", "channel"],
target="outcome_rate",
candidate_refinements=["region", "tenure_band", "channel"],
q_presets=["saturated", {"name": "bounded_shift", "radius": 0.5}],
ambiguity_limit=0.01,
bucket_budget=40,
search="beam",
)
Use kind="certificate" when the same search should produce a pass/fail
representation-stability certificate:
spec = us.AuditSpec(
kind="certificate",
public=["segment"],
hidden=["segment", "region", "tenure_band", "channel"],
target="outcome_rate",
candidate_refinements=["region", "tenure_band", "channel"],
q_presets=["saturated", {"name": "bounded_shift", "radius": 0.5}],
ambiguity_limit=0.01,
bucket_budget=40,
search="exhaustive",
)
Certificate specs require ambiguity_limit. By default, heuristic searches
such as greedy or beam are marked inconclusive rather than passed; set
exact_required=False when the certificate should cover only evaluated
candidates.
Frontier and certificate specs can also request experimental residopt screening for L2-budget stress tests:
spec = us.AuditSpec(
kind="certificate",
public=["segment"],
hidden=["segment", "region", "tenure_band", "channel"],
target="outcome_rate",
candidate_refinements=["region", "tenure_band", "channel"],
q_presets=[{"name": "l2_budget", "radius": 0.05}],
ambiguity_limit=0.01,
screening_backend="residopt",
)
The resulting frontier or certificate report records conservative endpoints, exact fallbacks, and avoided exact solves in Markdown and structured exports.
run_audit(...) also accepts a plain mapping, which is useful when loading a
spec from JSON or YAML:
run = us.run_audit(spec_mapping, rows_or_frame)
Q Presets¶
Specs use serializable Q descriptions:
"saturated"
{"name": "bounded_shift", "radius": 0.5}
{"name": "tv_budget", "radius": 0.1, "backend": "cvxpy"}
{"name": "tv_budget", "radius": 0.1, "backend": "cvxpy", "solver": "SCIP"}
{"name": "fiber_support_floor", "solver": "SCIP", "settings": {"min_active": 2, "min_share": 0.1}}
{"name": "observed"}
solver_options may also be supplied as a JSON object and are forwarded to
cvxpy.Problem.solve(...) for CVXPY-backed presets. Preset-specific values
that do not fit the standard radius or cost fields live under settings.
For non-serializable custom environments, custom constraint builders, or plugin-specific runtime objects, call the lower-level Python APIs directly.
Current Scope¶
The first AuditSpec slice covers public-descent reports, sensitivity reports,
and public-representation frontier search. Causal reporting suites, artifact
directory writers, and plugin-specific spec extensions can build on the same
shape without changing the report APIs.