Coverage for src / core / models.py: 100%

56 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-01-04 04:43 +0000

1"""Shared domain-agnostic dataclasses for mala. 

2 

3This module provides shared types that are used across multiple domains 

4(logging, validation, orchestrator) to avoid circular dependencies. 

5 

6Types: 

7- LockEventType: Enum for lock event types (acquired, waiting, released) 

8- LockEvent: A lock event from an agent 

9- ResolutionOutcome: Enum for issue resolution outcomes 

10- IssueResolution: Records how an issue was resolved 

11- ValidationArtifacts: Record of validation outputs for observability 

12- UnmetCriterion: Individual gap identified during epic verification 

13- EpicVerdict: Result of verifying an epic against its acceptance criteria 

14- EpicVerificationResult: Summary of a verification run across multiple epics 

15- RetryConfig: Configuration for retry behavior with exponential backoff 

16""" 

17 

18from __future__ import annotations 

19 

20from dataclasses import dataclass 

21from enum import Enum 

22from typing import TYPE_CHECKING, Literal 

23 

24if TYPE_CHECKING: 

25 from pathlib import Path 

26 

27 

28class LockEventType(Enum): 

29 """Types of lock events emitted by agents.""" 

30 

31 ACQUIRED = "acquired" 

32 WAITING = "waiting" 

33 RELEASED = "released" 

34 

35 

36@dataclass 

37class LockEvent: 

38 """A lock event from an agent. 

39 

40 Attributes: 

41 event_type: Type of lock event. 

42 agent_id: ID of the agent that emitted this event. 

43 lock_path: Path to the lock file. 

44 timestamp: Unix timestamp when the event occurred. 

45 """ 

46 

47 event_type: LockEventType 

48 agent_id: str 

49 lock_path: str 

50 timestamp: float 

51 

52 

53class ResolutionOutcome(Enum): 

54 """Outcome of issue resolution.""" 

55 

56 SUCCESS = "success" 

57 NO_CHANGE = "no_change" 

58 OBSOLETE = "obsolete" 

59 ALREADY_COMPLETE = "already_complete" 

60 

61 

62@dataclass(frozen=True) 

63class IssueResolution: 

64 """Records how an issue was resolved. 

65 

66 Attributes: 

67 outcome: The resolution outcome (success, no_change, obsolete). 

68 rationale: Explanation for the resolution. 

69 """ 

70 

71 outcome: ResolutionOutcome 

72 rationale: str 

73 

74 

75@dataclass 

76class ValidationArtifacts: 

77 """Record of validation outputs for observability. 

78 

79 Attributes: 

80 log_dir: Directory containing validation logs. 

81 worktree_path: Path to the worktree (if any). 

82 worktree_state: State of the worktree ("kept" or "removed"). 

83 coverage_report: Path to coverage report. 

84 e2e_fixture_path: Path to E2E fixture directory. 

85 """ 

86 

87 log_dir: Path 

88 worktree_path: Path | None = None 

89 worktree_state: Literal["kept", "removed"] | None = None 

90 coverage_report: Path | None = None 

91 e2e_fixture_path: Path | None = None 

92 

93 

94@dataclass 

95class UnmetCriterion: 

96 """Individual gap identified during epic verification. 

97 

98 Attributes: 

99 criterion: The acceptance criterion not met. 

100 evidence: Why it's considered unmet. 

101 priority: Issue priority matching Cerberus levels (0-3). 

102 P0/P1 are blocking, P2/P3 are non-blocking (informational). 

103 criterion_hash: SHA256 of criterion text, for deduplication. 

104 """ 

105 

106 criterion: str 

107 evidence: str 

108 priority: int # 0=P0 (blocking), 1=P1 (blocking), 2=P2 (non-blocking), 3=P3 (non-blocking) 

109 criterion_hash: str 

110 

111 

112@dataclass 

113class EpicVerdict: 

114 """Result of verifying an epic against its acceptance criteria. 

115 

116 Attributes: 

117 passed: Whether all acceptance criteria were met. 

118 unmet_criteria: List of criteria that were not satisfied. 

119 confidence: Model confidence in the verdict (0.0 to 1.0). 

120 reasoning: Explanation of the verification outcome. 

121 """ 

122 

123 passed: bool 

124 unmet_criteria: list[UnmetCriterion] 

125 confidence: float 

126 reasoning: str 

127 

128 

129@dataclass 

130class EpicVerificationResult: 

131 """Summary of a verification run across multiple epics. 

132 

133 Attributes: 

134 verified_count: Number of epics verified. 

135 passed_count: Number that passed verification. 

136 failed_count: Number that failed verification. 

137 verdicts: Mapping of epic_id to its verdict. 

138 remediation_issues_created: Issue IDs created for remediation. 

139 """ 

140 

141 verified_count: int 

142 passed_count: int 

143 failed_count: int 

144 verdicts: dict[str, EpicVerdict] 

145 remediation_issues_created: list[str] 

146 

147 

148@dataclass 

149class RetryConfig: 

150 """Configuration for retry behavior with exponential backoff. 

151 

152 Attributes: 

153 max_retries: Total retry attempts. 

154 initial_delay_ms: First retry delay in milliseconds. 

155 backoff_multiplier: Exponential backoff multiplier. 

156 max_delay_ms: Cap on retry delay in milliseconds. 

157 timeout_ms: Per-attempt timeout in milliseconds. 

158 """ 

159 

160 max_retries: int = 2 

161 initial_delay_ms: int = 1000 

162 backoff_multiplier: float = 2.0 

163 max_delay_ms: int = 30000 

164 timeout_ms: int = 120000