Response Field Reference

scoring_warnings — what it means, when you see it.

A field in every /v1/preflight response. Surfaces fail-open warnings from the scoring pipeline so you know exactly when one of Sgraal's many analytical modules hit a non-fatal exception. The decision is still produced; this field just makes the partial-failure visible.

What it is

Sgraal's preflight pipeline runs many analytical modules (the 10 core risk components plus dozens of analytics modules — see the API reference). Most of those modules wrap their computation in a try / except block: if any single module hits an exception, the pipeline catches it, records the failure in scoring_warnings, and keeps going with the remaining modules.

This is called fail-open behavior: a single sub-component failure does not abort the whole request. You still get back a recommended_action (one of USE_MEMORY / WARN / ASK_USER / BLOCK) computed from the modules that did succeed. The scoring_warnings field exists so you can see which modules failed, even though the overall response succeeded.

scoring_warnings is always an array. scoring_warnings_count is the same number as scoring_warnings.length. Both are always present in the response, even when empty.

Example

A typical /v1/preflight response excerpt with a single warning:

{
  "recommended_action": "BLOCK",
  "omega_mem_final": 100,
  ...
  "scoring_warnings": [
    {
      "module": "timestamp_integrity",
      "error": "'NoneType' object is not iterable"
    }
  ],
  "scoring_warnings_count": 1
}

Each warning carries a module field (which analytical module failed) and an error field (the truncated exception message, up to 200 characters). The decision (recommended_action) is still computed from the modules that did succeed.

When the module field says "unknown_module"

The scoring pipeline today does not name every internal module in the scoring_warnings entries. As of this snapshot, the six primary detection layers (timestamp integrity, identity drift, consensus collapse, provenance chain integrity, sync bleed, confidence calibration) are named accurately. Other analytical modules currently emit "module": "unknown_module" when they fail, even though the surrounding code knows which module raised.

This is a known transparency gap and is being closed in stages. Phase 1 (the six detection layers) is shipped. Phase 2 (the remaining easily-attributable sites) and Phase 3 (a structural helper-function refactor that makes "unknown_module" impossible to emit by accident) are tracked and scheduled. See the threat model for the broader "what we are and are not yet" framing.

What to do with scoring_warnings

Read it, but do not retry on it.

A non-empty scoring_warnings array means one or more sub-modules failed. It does not mean the request failed. The decision in recommended_action is final and was computed from the surviving modules. Re-issuing the same request typically reproduces the same warnings.

If you want a request-level retry signal, use a non-2xx HTTP status or a recommended_action of BLOCK with a domain-specific business rule on top — do not key retry behavior off scoring_warnings.

Log it.

Recording scoring_warnings alongside the request ID in your own logs makes incident response cheaper later. When a customer-side ticket arrives that traces back to a specific preflight call, the warning trail tells you whether a sub-module failed at scoring time — and which one, where named.

File an issue if it persists.

A steady stream of the same warning across many requests usually points to a stable bug rather than a transient glitch. Open an issue with the request ID, the module name (or "unknown_module" if not yet named), and the error string at hello@sgraal.com. Persistent warnings are exactly the kind of signal Sgraal's pre-customer audit cycle is designed to surface; customer-reported instances accelerate the fix sequence.

Treat it as observability, not as an alarm.

An empty scoring_warnings array does not mean "every module succeeded perfectly" any more than a non-empty array means "the request failed." The field is a transparency surface that lets you see partial-failure where it occurs. Use it the same way you'd use any other observability signal — log, aggregate, alert on persistent patterns, but do not gate request flow on it.

Roadmap

The transparency-gap closure proceeds in three phases:

  • Phase 1 — six detection layers named. Shipped. Customer-most-relevant warnings now carry their actual module names.
  • Phase 2 — remaining easily-attributable sites. Scheduled. Each site has the module name visible in the surrounding code; the fix is mechanical and incremental.
  • Phase 3 — helper-function refactor + CI lint. Scheduled. A required-parameter helper makes "unknown_module" impossible to introduce in new code; a CI lint rule guards against regression.

Phase 2 and Phase 3 are tracked separately in the project backlog. The conservative path is Phase 1 first, then Phase 3 (so the structural fix lands before the bulk-attribution sweep), but the operational ordering is flexible.

Versioning

Last reviewed: 2026-05-13.

This document is versioned in git at sgraal-ai/web-static. Previous revisions available via git log.

Related: /docs/api · /docs/threat-model · /docs/preflight-zk · /security