SDS-016: Semantic Failure Management (Debt & Incidents)

Document Type

Software Design Specification (SDS)

Purpose

Specifies the Semantic Failure Management subsystem, the “Organizational Immune System” responsible for:

This specification consolidates the former SDS-016 (Semantic Incidents) into a unified view.


1. Data Model: SemanticDebtItem

Defined as a JSON Schema (Draft-07).

Schema Source: schemas/events/governance/semantic-debt/v1/opened.schema.json (and related status schemas)

State transitions are governed by strict schema validation for each lifecycle event.

1.1. Incident-Linking Fields (Optional)

The following optional fields enable grouping under incidents (§7):

Field Type Description
incidentId string? FK to grouping SemanticIncident (nullable)
incidentRelationship enum? primary, secondary, duplicate, superseded
supersededBy string? If superseded, reference to superseding debtId

2. Event Envelope Specification

All SEA™ events, including Semantic Debt events, must use the canonical envelope.

Schema Source: schemas/events/envelope-v1.schema.json

1
2
3
4
5
6
7
8
{
  "specversion": "1.0",
  "id": "uuid",
  "type": "governance.semantic-debt.opened",
  "source": "//core/semantic-ledger",
  "time": "2024-01-01T12:00:00Z",
  "data": { ... }
}

2.1. Debt Event Types

Event Type Schema Trigger
governance.semantic-debt.opened opened.schema.json New item detected
governance.semantic-debt.updated updated.schema.json Fields changed
governance.semantic-debt.status-changed status-changed.schema.json Lifecycle change
governance.semantic-debt.superseded superseded.schema.json Merged/replaced

3. Deduplication Algorithm

To prevent “debt spam” from repeat executions:

3.1. Normalization

3.2. Dedupe Key Computation

Construct canonical JSON object with: failureClass, boundedContext, conceptIds, policyNames, detectorSignal, policyEvalMode.

1
dedupeKey = "sha256:" + sha256(canonicalJson)

3.3. Resolution Logic


4. Service Architecture

4.1. Consumers

4.2. Privacy Mode

Events can carry privacy.payloadMode = "aggregated" where sensitive details (specific PII in evidence) are omitted, allowing safe dashboarding.


5. Authority & Governance

Semantic Debt lifecycle transitions are governed by SDS-031: Authority & Ownership Boundaries.

5.1. Key Constraints

Transition Required Role Additional Constraints
openaccepted Domain Steward (R-DS) or Architecture Governor (R-AG) Separation of duties: acceptor ≠ reporter
acceptedmitigating Developer (R-DEV) with R-DS oversight Mitigation plan required for High/Critical
acceptedresolved Developer (R-DEV) Evidence of resolution required
Any → break-glass override Security Officer (R-SO) See SDS-031 §4.3 Break-glass Protocol

5.2. Audit Events

All status transitions emit events to the IFL per SDS-031 §6 (Mandatory Audit Artifacts):


6. Incident Integration Overview

Semantic Debt Items can be grouped under Semantic Incidents when multiple items share a common root cause. This addresses “debt spam” where the same underlying issue manifests as multiple items.

A SemanticIncident provides:

Sections 7-14 define the complete incident model (formerly SDS-016).


7. SemanticIncident Entity

7.1. JSON Schema

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://schemas.newsea.io/governance/semantic-incident/v1.schema.json",
  "title": "SemanticIncident",
  "description": "Groups multiple SemanticDebtItems under a common root cause.",
  "type": "object",
  "required": ["incidentId", "title", "status", "rootCause", "debtItems", "detectedAt", "detectedBy"],
  "properties": {
    "incidentId": {
      "type": "string",
      "pattern": "^inc:[a-f0-9]{12}$",
      "description": "Unique incident identifier"
    },
    "title": {
      "type": "string",
      "minLength": 10,
      "description": "Human-readable incident title"
    },
    "description": { "type": "string" },
    "status": {
      "type": "string",
      "enum": ["open", "triaging", "contained", "resolving", "resolved", "postmortem", "closed"]
    },
    "severity": {
      "type": "string",
      "enum": ["low", "medium", "high", "critical"]
    },
    "rootCause": { "$ref": "#/definitions/RootCause" },
    "debtItems": {
      "type": "array",
      "items": { "$ref": "#/definitions/DebtItemReference" },
      "minItems": 1
    },
    "affectedContexts": {
      "type": "array",
      "items": { "type": "string" }
    },
    "blastRadius": { "$ref": "#/definitions/BlastRadius" },
    "correlationPatterns": { "$ref": "#/definitions/CorrelationPatterns" },
    "timeline": {
      "type": "array",
      "items": { "$ref": "#/definitions/TimelineEntry" }
    },
    "owner": { "$ref": "#/definitions/Principal" },
    "detectedAt": { "type": "string", "format": "date-time" },
    "detectedBy": { "type": "string", "enum": ["automatic", "manual"] },
    "containedAt": { "type": "string", "format": "date-time" },
    "resolvedAt": { "type": "string", "format": "date-time" },
    "postmortemUrl": { "type": "string", "format": "uri" }
  },
  "definitions": {
    "RootCause": {
      "type": "object",
      "required": ["category", "summary"],
      "properties": {
        "category": {
          "type": "string",
          "enum": [
            "policy_contradiction", "schema_drift", "concept_collision",
            "translation_loss", "projection_mismatch", "external_dependency",
            "configuration_error", "unknown"
          ]
        },
        "summary": { "type": "string" },
        "technicalDetails": { "type": "string" },
        "affectedArtifact": { "type": "string" }
      }
    },
    "DebtItemReference": {
      "type": "object",
      "required": ["debtId", "relationship", "addedAt"],
      "properties": {
        "debtId": { "type": "string" },
        "relationship": {
          "type": "string",
          "enum": ["primary", "secondary", "duplicate", "superseded"]
        },
        "addedAt": { "type": "string", "format": "date-time" },
        "addedBy": { "type": "string" },
        "supersededBy": { "type": "string" }
      }
    },
    "BlastRadius": {
      "type": "object",
      "properties": {
        "conceptsAffected": { "type": "integer" },
        "policiesAffected": { "type": "integer" },
        "contextsAffected": { "type": "integer" },
        "consumersAffected": { "type": "integer" },
        "ciRunsBlocked": { "type": "integer" },
        "estimatedResolutionEffort": {
          "type": "string",
          "enum": ["trivial", "small", "medium", "large", "epic"]
        }
      }
    },
    "CorrelationPatterns": {
      "type": "object",
      "properties": {
        "correlationIds": { "type": "array", "items": { "type": "string" } },
        "nearKeyMatches": { "type": "array", "items": { "type": "string" } },
        "sharedConcepts": { "type": "array", "items": { "type": "string" } },
        "sharedPolicies": { "type": "array", "items": { "type": "string" } }
      }
    },
    "TimelineEntry": {
      "type": "object",
      "required": ["timestamp", "action", "actor"],
      "properties": {
        "timestamp": { "type": "string", "format": "date-time" },
        "action": { "type": "string" },
        "actor": { "type": "string" },
        "details": { "type": "string" }
      }
    },
    "Principal": {
      "type": "object",
      "required": ["principalId", "role"],
      "properties": {
        "principalId": { "type": "string" },
        "role": { "type": "string" }
      }
    }
  }
}

8. Incident Detection & Clustering

8.1. Automatic Creation Triggers

An incident is automatically created when ANY of the following conditions are detected:

Trigger Detection Logic Minimum Threshold
Same correlationId Multiple debt items share correlationId from single CI run ≥2 items in same run
Repeated nearKey matches dedupeKey similarity ≥85% across items ≥3 near-matches in 24h
Cross-context conflicts Same conceptId or policyId appears in debt across ≥2 bounded contexts ≥2 contexts
Policy contradiction cluster Multiple policy_contradiction failures reference same policy ≥3 items on same policy
Cascade pattern Debt item X references concept that is dependsOn for concept in debt item Y ≥2 dependency hops

8.2. Detection Algorithm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def detect_incidents(new_debt_item: SemanticDebtItem) -> Optional[SemanticIncident]:
    """Determines if a new debt item should be grouped into an existing or new incident."""
    
    # Strategy 1: Same correlation ID
    existing = find_incident_by_correlation_id(new_debt_item.correlationId)
    if existing:
        add_to_incident(existing, new_debt_item, relationship="secondary")
        return existing
    
    # Strategy 2: Near-key matching (fuzzy dedupe, Jaccard similarity ≥85%)
    near_matches = find_near_key_matches(new_debt_item.dedupeKey, threshold=0.85)
    if len(near_matches) >= 2:
        incident = find_or_create_incident_for_near_keys(near_matches + [new_debt_item])
        return incident
    
    # Strategy 3: Cross-context conflict detection
    cross_context_items = find_debt_items_by_concept(
        new_debt_item.affectedConcepts,
        exclude_context=new_debt_item.boundedContext
    )
    if len(cross_context_items) >= 1:
        incident = create_cross_context_incident(new_debt_item, cross_context_items)
        return incident
    
    # Strategy 4: Cascade detection (dependency graph, depth=2)
    dependent_debt = find_debt_on_dependencies(new_debt_item.affectedConcepts, depth=2)
    if dependent_debt:
        incident = create_cascade_incident(new_debt_item, dependent_debt)
        return incident
    
    # No incident detected - item remains standalone
    return None

8.3. Manual Incident Creation

Users with role R-DS or R-AG may manually create incidents via:


9. Incident-to-Debt Relationships

9.1. Relationship Topology

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────────────────────────────────────────────────────────────┐
│                    INCIDENT-DEBT TOPOLOGY                          │
├─────────────────────────────────────────────────────────────────────┤
│            ┌─────────────────────┐                                  │
│            │  SemanticIncident   │                                  │
│            │  (inc:abc123)       │                                  │
│            └─────────┬───────────┘                                  │
│      ┌───────────────┼───────────────┬──────────────────┐          │
│      ▼               ▼               ▼                  ▼          │
│ ┌─────────┐   ┌─────────┐   ┌─────────┐         ┌─────────┐       │
│ │ DebtItem│   │ DebtItem│   │ DebtItem│   ...   │ DebtItem│       │
│ │ primary │   │secondary│   │duplicate│         │supersede│       │
│ └─────────┘   └─────────┘   └─────────┘         └─────────┘       │
└─────────────────────────────────────────────────────────────────────┘

9.2. Relationship Types

Relationship Description CI Behavior
primary Root cause debt item Shown in dashboards; resolving this resolves incident
secondary Related debt item with same root cause Inherits resolution from primary
duplicate Exact or near-exact copy of another item Hidden from dashboards; auto-resolves with primary
superseded Replaced by a newer, more accurate debt item Marked read-only; shows superseding item link

9.3. FK Constraint

Every SemanticDebtItem MAY have an incidentId foreign key:

1
2
3
4
5
{
  "debtId": "debt-12345",
  "incidentId": "inc:abc123",    // nullable - standalone if null
  "incidentRelationship": "secondary"
}

Backward Compatibility: incidentId is OPTIONAL. Existing debt items without incidents continue to function. Migration is NOT required.


10. Incident Lifecycle

10.1. State Machine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──────────┐    triage()    ┌───────────┐   contain()   ┌────────────┐
│   open   │───────────────►│ triaging  │──────────────►│ contained  │
└──────────┘                └───────────┘               └────────────┘
     │                           │                            │
     │ auto-resolve()            │ reject()                   │ resolve_start()
     ▼                           ▼                            ▼
┌──────────┐               ┌───────────┐               ┌────────────┐
│ resolved │◄──────────────│   open    │               │ resolving  │
└──────────┘  escalate()   └───────────┘               └────────────┘
     │                                                        │
     │ postmortem()                                           │ resolve_complete()
     ▼                                                        ▼
┌────────────┐                                          ┌────────────┐
│ postmortem │◄─────────────────────────────────────────│ resolved   │
└────────────┘                                          └────────────┘
     │
     │ close()
     ▼
┌──────────┐
│  closed  │
└──────────┘

10.2. State Descriptions

State Description Entry Criteria Exit Criteria
open Incident detected, awaiting triage Auto-detection or manual creation Owner assigned + severity confirmed
triaging Owner investigating root cause Owner assigned Root cause identified OR escalated
contained Blast radius limited; workarounds in place Mitigation deployed All affected contexts stabilized
resolving Permanent fix in progress Resolution plan approved All debt items resolved
resolved All constituent debt items resolved All primary/secondary items resolved Postmortem scheduled
postmortem Lessons learned documented Postmortem meeting held Postmortem document approved
closed Incident complete Postmortem approved N/A (terminal state)

10.3. Authority Requirements

Transition Required Role Additional Constraints
opentriaging R-DS or R-AG Owner assignment required
triagingcontained R-DS Mitigation plan documented
containedresolving R-DS with R-AG approval for cross-context Resolution proposal approved
resolvingresolved R-DEV (with R-DS verification) All debt items resolved
resolvedpostmortem R-AG or R-SO for Critical Postmortem scheduled
postmortemclosed R-AG Postmortem document linked

11. Merge & Supersede Rules

11.1. Automatic Merge

Two debt items are automatically merged into one incident when:

Condition Action
dedupeKey exact match Mark newer as duplicate; update evidence on original
dedupeKey similarity ≥95% Prompt user to confirm merge; suggest duplicate
Same conceptId + same failureClass within 1 hour Auto-group into incident if not already grouped

11.2. Supersede Rules

A debt item is superseded when:

Trigger Behavior
User manually marks as superseded Link to superseding item required
Same concept + higher severity detected Old item auto-superseded by new
Resolution invalidated by new failure Reopened item supersedes resolved item

11.3. Merge Algorithm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def merge_debt_items(target: SemanticDebtItem, source: SemanticDebtItem) -> SemanticDebtItem:
    """Merges source into target. Target becomes the surviving item."""
    # Preserve highest severity
    if severity_rank(source.severity) > severity_rank(target.severity):
        target.severity = source.severity
    
    # Append evidence
    target.evidence.extend(source.evidence)
    
    # Union affected concepts
    target.affectedConcepts = list(set(target.affectedConcepts + source.affectedConcepts))
    
    # Mark source as superseded
    source.status = "superseded"
    source.supersededBy = target.debtId
    emit_event("governance.semantic-debt.superseded", source)
    
    # If source was in an incident, transfer to target's incident
    if source.incidentId and not target.incidentId:
        target.incidentId = source.incidentId
    
    emit_event("governance.semantic-debt.updated", target)
    return target

12. Incident Events & Queries

12.1. Incident Event Types

Event Type Trigger Required Fields
governance.incident.created Incident created incidentId, title, debtItems, detectedBy, timestamp
governance.incident.debt-added Debt item added incidentId, debtId, relationship, addedBy, timestamp
governance.incident.debt-removed Debt item removed incidentId, debtId, removedBy, reason, timestamp
governance.incident.status-changed Lifecycle transition incidentId, from, to, actor, timestamp
governance.incident.owner-assigned Owner assigned/changed incidentId, previousOwner, newOwner, timestamp
governance.incident.postmortem-linked Postmortem attached incidentId, postmortemUrl, timestamp
governance.incident.closed Incident closed incidentId, resolution, timestamp

12.2. Example Event

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "specversion": "1.0",
  "id": "evt-uuid-12345",
  "type": "governance.incident.created",
  "source": "//governance/incident-service",
  "time": "2025-12-22T10:35:00Z",
  "data": {
    "incidentId": "inc:abc123def456",
    "title": "Cross-context policy contradiction in Billing/Payments",
    "severity": "high",
    "rootCause": {
      "category": "policy_contradiction",
      "summary": "Tax calculation policy conflicts between Billing and Payments contexts"
    },
    "debtItems": [
      { "debtId": "debt-001", "relationship": "primary" },
      { "debtId": "debt-002", "relationship": "secondary" }
    ],
    "detectedBy": "automatic",
    "detectedAt": "2025-12-22T10:35:00Z"
  }
}

12.3. Dashboard SPARQL Queries

Active Incidents with Blast Radius

1
2
3
4
5
6
7
8
9
10
11
12
13
PREFIX sea-inc: <http://sea-forge.com/schema/incident#>

SELECT ?incident ?title ?severity (COUNT(?debt) AS ?debtCount) ?status
WHERE {
  ?incident a sea-inc:SemanticIncident ;
            sea-inc:title ?title ;
            sea-inc:severity ?severity ;
            sea-inc:status ?status ;
            sea-inc:hasDebtItem ?debt .
  FILTER (?status IN ("open", "triaging", "contained", "resolving"))
}
GROUP BY ?incident ?title ?severity ?status
ORDER BY DESC(?severity) DESC(?debtCount)

Cross-Context Incidents

1
2
3
4
5
6
7
8
SELECT ?incident ?title (GROUP_CONCAT(?context; separator=", ") AS ?contexts)
WHERE {
  ?incident a sea-inc:SemanticIncident ;
            sea-inc:title ?title ;
            sea-inc:affectedContext ?context .
}
GROUP BY ?incident ?title
HAVING (COUNT(?context) > 1)

13. KG Ontology Extension

13.1. Incident Ontology (SEA-INC)

Prefix: sea-inc: <http://sea-forge.com/schema/incident#>

Class/Property Type Description
sea-inc:SemanticIncident Class Groups related debt items under common root cause
sea-inc:RootCause Class The underlying cause of the incident
sea-inc:hasDebtItem Property Links Incident to constituent DebtItems
sea-inc:hasRootCause Property Links Incident to RootCause
sea-inc:affectedContext Property Links Incident to affected BoundedContext
sea-inc:owner Property Links Incident to responsible Principal
sea-inc:status Property Current lifecycle state
sea-inc:severity Property Aggregate severity
sea-inc:supersedes Property Links DebtItem to superseded DebtItem

13.2. Projection Mappings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Incident creation
<sea:incident:{incidentId}> a sea-inc:SemanticIncident ;
    rdfs:label "{title}" ;
    sea-inc:status "{status}" ;
    sea-inc:severity "{severity}" ;
    sea-inc:detectedAt "{detectedAt}"^^xsd:dateTime .

# Link to root cause
<sea:incident:{incidentId}> sea-inc:hasRootCause [
    a sea-inc:RootCause ;
    sea-inc:category "{rootCause.category}" ;
    rdfs:comment "{rootCause.summary}"
] .

# Link to debt items
<sea:incident:{incidentId}> sea-inc:hasDebtItem <sea:debt:{debtId}> .

# Supersession relationship
<sea:debt:{newDebtId}> sea-inc:supersedes <sea:debt:{oldDebtId}> .

13.3. IFL Transaction Types

Transaction Type Description
INCIDENT_CREATE Creates new SemanticIncident record
INCIDENT_ADD_DEBT Links debt item to incident
INCIDENT_REMOVE_DEBT Unlinks debt item from incident
INCIDENT_STATUS_CHANGE Transitions incident lifecycle state
DEBT_SUPERSEDE Marks debt item as superseded by another
DEBT_MERGE Merges evidence from one item into another

14. CLI Commands

14.1. sea-incident create

1
2
3
4
5
6
sea-incident create \
  --title "Cross-context policy contradiction" \
  --debt-items debt-001,debt-002,debt-003 \
  --root-cause-category policy_contradiction \
  --severity high \
  --out incident.json

14.2. sea-incident add-debt

1
2
3
4
sea-incident add-debt \
  --incident inc:abc123 \
  --debt-id debt-004 \
  --relationship secondary

14.3. sea-incident status

1
2
3
4
sea-incident status \
  --incident inc:abc123 \
  --to contained \
  --mitigation "Feature flag deployed to disable conflicting calculation"

14.4. sea-incident query

1
2
3
4
sea-incident query \
  --status open,triaging \
  --severity high,critical \
  --format table


16. Changelog

Version Date Author Change
1.0.0 2025-12-31 SEA-Forge™ Consolidated SDS-016 (Semantic Incidents) into unified specification
0.1.0 2024-01-01 SEA-Forge™ Initial draft (Semantic Debt Ledger only)