Skip to content

Scoring

Deterministic gates and the audit record.

score

Scoring a run: deterministic gates first, human or auditor judgement second.

Gates are computed in Python from the trace and cannot be negotiated with: did every node actually execute, did the evaluation node produce a valid number, did nodes that claim tool usage make verified tool calls, and were artifacts produced. A run that fails a gate scores 0.0.

compute_gates

compute_gates(trace, workflow)

Computes all deterministic integrity gates against a completed run trace.

Parameters:

Name Type Description Default
trace Trace

The completed Trace record.

required
workflow Workflow

The Workflow specification that was executed.

required

Returns:

Type Description
list[Gate]

A list of Gate results.

Source code in python/src/science_adk/score.py
def compute_gates(trace: Trace, workflow: Workflow) -> list[Gate]:
    """Computes all deterministic integrity gates against a completed run trace.

    Args:
      trace: The completed Trace record.
      workflow: The Workflow specification that was executed.

    Returns:
      A list of Gate results.
    """
    return [
        _gate_completed(trace),
        _gate_all_nodes_ran(trace, workflow),
        _gate_measured(trace, workflow),
        _gate_evaluation_is_numeric(trace, workflow),
        _gate_produced_artifacts(trace),
        _gate_tool_claims_hold(trace, workflow),
    ]

score_run

score_run(trace, workflow, target_metric='', target_value=None)

Constructs the deterministic score structure for a completed run.

Parameters:

Name Type Description Default
trace Trace

The completed Trace.

required
workflow Workflow

The Workflow specification.

required
target_metric str

The metric name being targeted.

''
target_value float | None

The target value threshold.

None

Returns:

Type Description
Score

A populated Score instance.

Source code in python/src/science_adk/score.py
def score_run(
    trace: Trace,
    workflow: Workflow,
    target_metric: str = "",
    target_value: float | None = None,
) -> Score:
    """Constructs the deterministic score structure for a completed run.

    Args:
      trace: The completed Trace.
      workflow: The Workflow specification.
      target_metric: The metric name being targeted.
      target_value: The target value threshold.

    Returns:
      A populated Score instance.
    """
    observed = _observed_value(trace, workflow)
    return Score(
        run_id=trace.run_id,
        gates=compute_gates(trace, workflow),
        target_metric=target_metric,
        target_value=target_value,
        observed_value=observed,
    )

record_audit

record_audit(score, pillars, rationale)

Records audit judgements and rationale onto a Score object.

Parameters:

Name Type Description Default
score Score

The target Score object to augment.

required
pillars dict[str, float]

Dictionary mapping SCORE_PILLARS to scores in [0.0, 1.0].

required
rationale str

Written explanation supporting the evaluation.

required

Returns:

Type Description
Score

The updated Score instance.

Raises:

Type Description
ValueError

If pillars are unknown, missing, or rationale is empty.

Source code in python/src/science_adk/score.py
def record_audit(
    score: Score,
    pillars: dict[str, float],
    rationale: str,
) -> Score:
    """Records audit judgements and rationale onto a Score object.

    Args:
      score: The target Score object to augment.
      pillars: Dictionary mapping SCORE_PILLARS to scores in [0.0, 1.0].
      rationale: Written explanation supporting the evaluation.

    Returns:
      The updated Score instance.

    Raises:
      ValueError: If pillars are unknown, missing, or rationale is empty.
    """
    unknown = sorted(set(pillars) - set(SCORE_PILLARS))
    if unknown:
        raise ValueError(
            f"Unknown pillar(s): {', '.join(unknown)}. Expected:"
            f" {', '.join(SCORE_PILLARS)}"
        )
    missing = sorted(set(SCORE_PILLARS) - set(pillars))
    if missing:
        raise ValueError(f"Missing rating for pillar(s): {', '.join(missing)}")
    if not rationale.strip():
        raise ValueError("An audit needs a rationale explaining the ratings.")

    score.pillars = {k: max(0.0, min(1.0, float(v))) for k, v in pillars.items()}
    score.rationale = rationale.strip()
    score.audited_at = utcnow()
    return score

summarize

summarize(score)

Generates a formatted human-readable summary string of the score verdict.

Parameters:

Name Type Description Default
score Score

The Score object to summarize.

required

Returns:

Type Description
str

Formatted multi-line summary string.

Source code in python/src/science_adk/score.py
def summarize(score: Score) -> str:
    """Generates a formatted human-readable summary string of the score verdict.

    Args:
      score: The Score object to summarize.

    Returns:
      Formatted multi-line summary string.
    """
    lines: list[str] = []
    for gate in score.gates:
        mark = "pass" if gate.passed else "FAIL"
        lines.append(f"  [{mark}] {gate.name}: {gate.detail}")

    if not score.gates_passed:
        lines.append("")
        lines.append("Score: 0.00 — a failed gate means this run is not a result.")
        return "\n".join(lines)

    if not score.audited:
        lines.append("")
        lines.append(
            "Gates passed, but the run has not been audited. It has no score"
            " yet and must not be reported as a finding."
        )
        return "\n".join(lines)

    lines.append("")
    for pillar, value in sorted(score.pillars.items()):
        lines.append(f"  {pillar.replace('_', ' ')}: {value:.2f}")
    lines.append(f"  overall: {score.value:.2f}")
    if score.target_value is not None and score.observed_value is not None:
        verdict = "met" if score.meets_target else "not met"
        lines.append(
            f"  target {score.target_metric} >= {score.target_value:g}: observed"
            f" {score.observed_value:g} ({verdict})"
        )
    return "\n".join(lines)