55Part of the standalone ``epistemic`` library. Zero external dependencies.
66 from epistemic import RecoveryOperator, RecoveryProposal
77"""
8+
89from __future__ import annotations
910
1011from dataclasses import dataclass
@@ -42,11 +43,11 @@ class RecoveryProposal:
4243class RecoveryOperator :
4344 """Propose minimal recovery actions for Failure Modes and Logic Knots.
4445
45- from epistemic import RecoveryOperator
46+ from epistemic import RecoveryOperator
4647
47- operator = RecoveryOperator()
48- proposals = operator.propose(artifacts, stress_result)
49- print(operator.format_proposals(proposals))
48+ operator = RecoveryOperator()
49+ proposals = operator.propose(artifacts, stress_result)
50+ print(operator.format_proposals(proposals))
5051 """
5152
5253 def propose (
@@ -78,64 +79,78 @@ def _propose_for_failure(
7879
7980 if "vagueness" in challenge :
8081 strategy = (
81- RecoveryStrategy .QUANTIFY if "unquantified" in challenge
82+ RecoveryStrategy .QUANTIFY
83+ if "unquantified" in challenge
8284 else RecoveryStrategy .QUANTIFY
8385 )
84- proposals .append (RecoveryProposal (
85- artifact_id = artifact .artifact_id ,
86- failure_mode_challenge = fm .challenge ,
87- strategy = strategy ,
88- description = f"Replace imprecise language in { artifact .artifact_id } ." ,
89- suggested_change = fm .recovery_hint or "Replace vague terms with measurable criteria." , # noqa: E501
90- priority = priority ,
91- ))
86+ proposals .append (
87+ RecoveryProposal (
88+ artifact_id = artifact .artifact_id ,
89+ failure_mode_challenge = fm .challenge ,
90+ strategy = strategy ,
91+ description = f"Replace imprecise language in { artifact .artifact_id } ." ,
92+ suggested_change = fm .recovery_hint
93+ or "Replace vague terms with measurable criteria." , # noqa: E501
94+ priority = priority ,
95+ )
96+ )
9297 elif "falsifiability" in challenge or "no test" in challenge :
93- proposals .append (RecoveryProposal (
94- artifact_id = artifact .artifact_id ,
95- failure_mode_challenge = fm .challenge ,
96- strategy = RecoveryStrategy .FALSIFY ,
97- description = f"Add a test for { artifact .artifact_id } ." ,
98- suggested_change = f"Add a test entry that covers: { artifact .source_text [:80 ]} " ,
99- priority = priority ,
100- ))
98+ proposals .append (
99+ RecoveryProposal (
100+ artifact_id = artifact .artifact_id ,
101+ failure_mode_challenge = fm .challenge ,
102+ strategy = RecoveryStrategy .FALSIFY ,
103+ description = f"Add a test for { artifact .artifact_id } ." ,
104+ suggested_change = f"Add a test entry that covers: { artifact .source_text [:80 ]} " ,
105+ priority = priority ,
106+ )
107+ )
101108 elif "observability" in challenge or "boundary" in challenge :
102- proposals .append (RecoveryProposal (
103- artifact_id = artifact .artifact_id ,
104- failure_mode_challenge = fm .challenge ,
105- strategy = RecoveryStrategy .CONSTRAIN ,
106- description = f"Add epistemic boundary to { artifact .artifact_id } ." ,
107- suggested_change = "Declare scope, assumptions, and platform constraints." ,
108- priority = priority ,
109- ))
109+ proposals .append (
110+ RecoveryProposal (
111+ artifact_id = artifact .artifact_id ,
112+ failure_mode_challenge = fm .challenge ,
113+ strategy = RecoveryStrategy .CONSTRAIN ,
114+ description = f"Add epistemic boundary to { artifact .artifact_id } ." ,
115+ suggested_change = "Declare scope, assumptions, and platform constraints." ,
116+ priority = priority ,
117+ )
118+ )
110119 if not artifact .propositions :
111- proposals .append (RecoveryProposal (
120+ proposals .append (
121+ RecoveryProposal (
122+ artifact_id = artifact .artifact_id ,
123+ failure_mode_challenge = fm .challenge ,
124+ strategy = RecoveryStrategy .DECOMPOSE ,
125+ description = f"Add propositions to { artifact .artifact_id } — currently empty." , # noqa: E501
126+ suggested_change = "Add a description as a testable claim." ,
127+ priority = 1 ,
128+ )
129+ )
130+ elif "irreducibility" in challenge or "compound" in challenge :
131+ proposals .append (
132+ RecoveryProposal (
112133 artifact_id = artifact .artifact_id ,
113134 failure_mode_challenge = fm .challenge ,
114135 strategy = RecoveryStrategy .DECOMPOSE ,
115- description = f"Add propositions to { artifact .artifact_id } — currently empty." ,
116- suggested_change = "Add a description as a testable claim." ,
117- priority = 1 ,
118- ))
119- elif "irreducibility" in challenge or "compound" in challenge :
120- proposals .append (RecoveryProposal (
121- artifact_id = artifact .artifact_id ,
122- failure_mode_challenge = fm .challenge ,
123- strategy = RecoveryStrategy .DECOMPOSE ,
124- description = f"Decompose { artifact .artifact_id } into independent beliefs." ,
125- suggested_change = "Split into separate beliefs, each with a single proposition." ,
126- estimated_cost = "medium" ,
127- priority = priority ,
128- ))
136+ description = f"Decompose { artifact .artifact_id } into independent beliefs." ,
137+ suggested_change = "Split into separate beliefs, each with a single proposition." ,
138+ estimated_cost = "medium" ,
139+ priority = priority ,
140+ )
141+ )
129142 elif "confidence" in challenge :
130- proposals .append (RecoveryProposal (
131- artifact_id = artifact .artifact_id ,
132- failure_mode_challenge = fm .challenge ,
133- strategy = RecoveryStrategy .FALSIFY ,
134- description = f"Raise confidence for P1 belief { artifact .artifact_id } ." ,
135- suggested_change = "Add test coverage, evidence citations, and mark as stress-tested." , # noqa: E501
136- estimated_cost = "medium" ,
137- priority = 1 ,
138- ))
143+ proposals .append (
144+ RecoveryProposal (
145+ artifact_id = artifact .artifact_id ,
146+ failure_mode_challenge = fm .challenge ,
147+ strategy = RecoveryStrategy .FALSIFY ,
148+ description = f"Raise confidence for P1 belief { artifact .artifact_id } ." ,
149+ suggested_change = "Add test coverage, evidence citations, and mark as stress-tested." , # noqa: E501
150+ estimated_cost = "medium" ,
151+ priority = 1 ,
152+ )
153+ )
139154
140155 return proposals
141156
@@ -148,28 +163,32 @@ def _propose_for_knot(
148163 reason : str ,
149164 ) -> list [RecoveryProposal ]:
150165 if "duplicate" in reason .lower ():
151- return [RecoveryProposal (
166+ return [
167+ RecoveryProposal (
168+ artifact_id = id1 ,
169+ failure_mode_challenge = f"Logic Knot: { reason [:60 ]} " ,
170+ strategy = RecoveryStrategy .DEPRECATE ,
171+ description = f"Resolve duplicate ID conflict between { id1 } and { id2 } ." ,
172+ suggested_change = "Merge or rename one with a unique ID." ,
173+ priority = 1 ,
174+ )
175+ ]
176+ return [
177+ RecoveryProposal (
152178 artifact_id = id1 ,
153179 failure_mode_challenge = f"Logic Knot: { reason [:60 ]} " ,
154- strategy = RecoveryStrategy .DEPRECATE ,
155- description = f"Resolve duplicate ID conflict between { id1 } and { id2 } ." ,
156- suggested_change = "Merge or rename one with a unique ID." ,
180+ strategy = RecoveryStrategy .RESOLVE ,
181+ description = f"Resolve Logic Knot between { id1 } and { id2 } ." ,
182+ suggested_change = (
183+ f"Review both { id1 } and { id2 } . Options:\n "
184+ " 1. Narrow epistemic boundary of one\n "
185+ " 2. Supersede one (mark as DEPRECATED)\n "
186+ " 3. Decompose both into non-conflicting primitives"
187+ ),
188+ estimated_cost = "medium" ,
157189 priority = 1 ,
158- )]
159- return [RecoveryProposal (
160- artifact_id = id1 ,
161- failure_mode_challenge = f"Logic Knot: { reason [:60 ]} " ,
162- strategy = RecoveryStrategy .RESOLVE ,
163- description = f"Resolve Logic Knot between { id1 } and { id2 } ." ,
164- suggested_change = (
165- f"Review both { id1 } and { id2 } . Options:\n "
166- " 1. Narrow epistemic boundary of one\n "
167- " 2. Supersede one (mark as DEPRECATED)\n "
168- " 3. Decompose both into non-conflicting primitives"
169- ),
170- estimated_cost = "medium" ,
171- priority = 1 ,
172- )]
190+ )
191+ ]
173192
174193 def format_proposals (self , proposals : list [RecoveryProposal ]) -> str :
175194 if not proposals :
@@ -182,7 +201,9 @@ def format_proposals(self, proposals: list[RecoveryProposal]) -> str:
182201 "" ,
183202 ]
184203 for i , p in enumerate (proposals , 1 ):
185- lines .append (f"{ i } . [{ p .strategy .value .upper ()} ] { p .artifact_id } (cost: { p .estimated_cost } )" ) # noqa: E501
204+ lines .append (
205+ f"{ i } . [{ p .strategy .value .upper ()} ] { p .artifact_id } (cost: { p .estimated_cost } )"
206+ ) # noqa: E501
186207 lines .append (f" Problem: { p .failure_mode_challenge } " )
187208 lines .append (f" Action: { p .description } " )
188209 lines .append (f" Change: { p .suggested_change [:200 ]} " )
0 commit comments