Skip to main content
INFORMATIVEACTIVEDocumentation Governance

Learning Invariants

1. Purpose​

Learning invariants define validation rules that LearningSamples must satisfy. These rules ensure structural integrity, enable interoperability, and support quality assessment.

Source of Truth: schemas/v2/invariants/learning-invariants.yaml

2. Core Invariants​

These invariants apply to all LearningSamples regardless of family.

Invariant IDPathRuleDescription
learning_sample_id_is_uuidsample_iduuid-v4Sample ID must be UUID v4 format
learning_sample_family_non_emptysample_familynon-empty-stringSample family is required
learning_sample_created_at_isocreated_atiso-datetimeCreated timestamp must be ISO 8601
learning_sample_has_input_sectioninputobject-requiredInput section is required
learning_sample_has_output_sectionoutputobject-requiredOutput section is required
learning_sample_feedback_label_validmeta.human_feedback_labelenum(approved, rejected, not_reviewed)If present, must be valid enum
learning_sample_source_flow_non_emptymeta.source_flow_idnon-empty-stringIf present, must be non-empty

3. Intent Resolution Family Invariants​

These invariants apply only when sample_family == "intent_resolution".

Invariant IDPathRuleDescription
learning_intent_has_intent_idinput.intent_idnon-empty-stringIntent resolution samples must have intent_id in input
learning_intent_quality_label_validoutput.resolution_quality_labelenum(good, acceptable, bad, unknown)If present, quality label must be valid enum

4. Delta Impact Family Invariants​

These invariants apply only when sample_family == "delta_impact".

Invariant IDPathRuleDescription
learning_delta_has_delta_idinput.delta_idnon-empty-stringDelta impact samples must have delta_id in input
learning_delta_scope_validoutput.impact_scopeenum(local, module, system, global)Impact scope must be valid enum
learning_delta_risk_validstate.risk_levelenum(low, medium, high, critical)Risk level must be valid enum

5. Invariant Application Logic​

5.1 Conditional Application​

Some invariants are conditional based on:

  • Field existence: Applied only when the field is present
  • Sample family: Applied only for specific sample_family values
# Example from learning-invariants.yaml
- id: learning_intent_has_intent_id
scope: learning_sample
path: input.intent_id
rule: non-empty-string
description: "Intent resolution samples must have intent_id in input"
note: "Apply when sample_family == intent_resolution"

5.2 Implementation Notes​

From the invariants file:

If the invariant engine does not support conditional application, these should be enforced at the schema level (already done in family-specific schemas) or during runtime validation. These invariants provide an additional validation layer.

5.3 Validation Order​

  1. Core invariants first: Validate structure
  2. Family-specific invariants: Based on sample_family value
  3. Optional field validation: Only if field is present

6. Compliance Summary​

CategoryCountEnforcement
Core Invariants7Always apply
Intent Family2When sample_family == intent_resolution
Delta Family3When sample_family == delta_impact
Total12

[!NOTE] Other families (pipeline_outcome, confirm_decision, graph_evolution, multi_agent_coordination) use the Core Schema and rely on core invariants only.

7. Validation Example​

def validate_learning_sample(sample: dict) -> list[str]:
"""
Validate a LearningSample against invariants.
Returns list of violation messages.
"""
violations = []

# Core invariants
if not is_uuid_v4(sample.get('sample_id')):
violations.append("learning_sample_id_is_uuid: sample_id must be UUID v4")

if not sample.get('sample_family'):
violations.append("learning_sample_family_non_empty: sample_family required")

if not is_iso_datetime(sample.get('created_at')):
violations.append("learning_sample_created_at_iso: created_at must be ISO 8601")

if 'input' not in sample:
violations.append("learning_sample_has_input_section: input required")

if 'output' not in sample:
violations.append("learning_sample_has_output_section: output required")

# Conditional: Meta field validation
if sample.get('meta', {}).get('human_feedback_label'):
if sample['meta']['human_feedback_label'] not in ['approved', 'rejected', 'not_reviewed']:
violations.append("learning_sample_feedback_label_valid: invalid enum")

# Family-specific: intent_resolution
if sample.get('sample_family') == 'intent_resolution':
if not sample.get('input', {}).get('intent_id'):
violations.append("learning_intent_has_intent_id: intent_id required")

quality = sample.get('output', {}).get('resolution_quality_label')
if quality and quality not in ['good', 'acceptable', 'bad', 'unknown']:
violations.append("learning_intent_quality_label_valid: invalid enum")

# Family-specific: delta_impact
if sample.get('sample_family') == 'delta_impact':
if not sample.get('input', {}).get('delta_id'):
violations.append("learning_delta_has_delta_id: delta_id required")

impact_scope = sample.get('output', {}).get('impact_scope')
if impact_scope and impact_scope not in ['local', 'module', 'system', 'global']:
violations.append("learning_delta_scope_valid: invalid impact_scope")

risk_level = sample.get('state', {}).get('risk_level')
if risk_level and risk_level not in ['low', 'medium', 'high', 'critical']:
violations.append("learning_delta_risk_valid: invalid risk_level")

return violations

Total Invariants: 12 (7 core + 2 intent + 3 delta) Validation: Schema-level + runtime validation Source: schemas/v2/invariants/learning-invariants.yaml