Menu

#424 Make the algebra version real: stamp ALGEBRA_VERSION, persist the classified algebra per decision, fail conservative on mismatch

open
nobody
2026-08-20
2026-08-20
Anonymous
No

Originally created by: fu351

The gap

models.py declares ALGEBRA_VERSION = 1 and the docs describe the action algebra as a versioned vocabulary. Nothing enforces it: Algebra has no version field, no code reads the constant, no test covers it. The 2026-08-19 subjective-layer hardening audit flagged this as a claim with no enforcement behind it.

It is harmless today only because an Algebra never leaves the process — inference builds it, the engine scores it, and it is gone. The day one is persisted or exchanged, the failure mode is silent: pydantic drops an unknown field from a newer writer, so an old reader scores the action missing a dimension with no signal that anything was lost. In a risk engine, that is a silent under-classification channel.

The plan

Versioning only means something once an algebra crosses a writer/reader boundary, so this issue builds that boundary and the enforcement together:

  1. Persist the classified algebra on each decision row. Store the seven dimensions as their enum values plus classification_confidence and version — classes and floats only, never raw targets or payloads, same redaction discipline as every other column. Independent value: the decision log becomes replayable (feed real recorded traffic back through the benchmark harness, analyze classification drift across releases).
  2. Stamp the version. Add version: int = ALGEBRA_VERSION to Algebra so every serialized copy carries its vocabulary version.
  3. Fail conservative on read. A stored algebra with a missing/unknown version or an unrecognized enum value is treated as unclassified (elevated sensitivity, low confidence) — never a crash on the decision path, never a silent coercion, never a downgrade. Raise-only by construction: version confusion can only make Doberman more suspicious.

Acceptance

  • Decision rows carry the algebra columns; a test proves a synthetic secret in the action's target never appears in them.
  • Round-trip test: same-version read reproduces the algebra exactly.
  • Mismatch tests: unknown version and unknown enum value both resolve to the unclassified/conservative form, and the engine still returns a verdict.
  • ALGEBRA_VERSION bumps are documented in the constant's docstring (when to bump, what a reader must do).

Scope notes

Additive only — no existing classification changes (that would be level-8). The read-side conservative rule reuses the existing is_unclassified / UNCLASSIFIED_SENSITIVITY_FLOOR machinery in subjective/infer.py rather than inventing a new path.

Discussion


Log in to post a comment.