Index
healing
¶
Self-healing module for Marianne.
Provides automatic diagnosis and remediation of common configuration and execution errors. The healing system activates when: 1. All retries have been exhausted 2. The error is in a healable category 3. The --self-healing flag is enabled
Public exports: - ErrorContext: Rich diagnostic context for failed executions - DiagnosisEngine: Analyzes errors and suggests remedies - Remedy: Protocol for remediation actions - RemedyCategory: AUTOMATIC, SUGGESTED, or DIAGNOSTIC - RemedyRegistry: Registry of available remedies - SelfHealingCoordinator: Orchestrates the healing process - HealingReport: Results of a healing attempt - create_default_registry: Factory for built-in remedies
Classes¶
ErrorContext
dataclass
¶
ErrorContext(error_code, error_message, error_category, exception=None, exit_code=None, signal=None, stdout_tail='', stderr_tail='', config_path=None, config=None, workspace=None, sheet_number=0, working_directory=None, environment=dict(), retry_count=0, max_retries=0, previous_errors=list(), raw_config_yaml=None, validation_details=list())
Rich context gathered when an error occurs.
Provides all information needed by the diagnosis engine and remedies to understand and potentially fix the error.
Attributes:
| Name | Type | Description |
|---|---|---|
error_code |
str
|
Structured error code (e.g., E601, E304) |
error_message |
str
|
Human-readable error description |
error_category |
str
|
High-level category (preflight, configuration, etc.) |
exception |
Exception | None
|
Original exception if available |
exit_code |
int | None
|
Process exit code (if applicable) |
signal |
int | None
|
Termination signal (if applicable) |
stdout_tail |
str
|
Last portion of stdout output |
stderr_tail |
str
|
Last portion of stderr output |
config_path |
Path | None
|
Path to the job configuration file |
config |
JobConfig | None
|
Parsed JobConfig object |
workspace |
Path | None
|
Workspace directory path |
sheet_number |
int
|
Current sheet number |
working_directory |
Path | None
|
Backend working directory |
environment |
dict[str, str]
|
Relevant environment variables |
retry_count |
int
|
Number of retries attempted |
max_retries |
int
|
Maximum retries configured |
previous_errors |
list[str]
|
Error codes from previous attempts |
Functions¶
from_execution_result
classmethod
¶
from_execution_result(result, config, config_path, sheet_number, error_code, error_message, error_category, retry_count=0, max_retries=0, previous_errors=None)
Create context from an execution result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
ExecutionResult
|
The failed execution result. |
required |
config
|
JobConfig
|
Job configuration. |
required |
config_path
|
Path | None
|
Path to config file. |
required |
sheet_number
|
int
|
Current sheet number. |
required |
error_code
|
str
|
Classified error code. |
required |
error_message
|
str
|
Error message. |
required |
error_category
|
str
|
Error category. |
required |
retry_count
|
int
|
Current retry count. |
0
|
max_retries
|
int
|
Maximum retries allowed. |
0
|
previous_errors
|
list[str] | None
|
Error codes from previous attempts. |
None
|
Returns:
| Type | Description |
|---|---|
ErrorContext
|
ErrorContext with all diagnostic information. |
Source code in src/marianne/healing/context.py
from_preflight_error
classmethod
¶
Create context from a preflight check failure.
Preflight errors occur before execution starts, so there's no ExecutionResult. This is common for validation errors like missing workspace directories or invalid templates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
JobConfig
|
Job configuration. |
required |
config_path
|
Path | None
|
Path to config file. |
required |
error_code
|
str
|
Preflight error code. |
required |
error_message
|
str
|
Error description. |
required |
sheet_number
|
int
|
Sheet number (0 if global). |
0
|
raw_yaml
|
str | None
|
Raw YAML content for template analysis. |
None
|
Returns:
| Type | Description |
|---|---|
ErrorContext
|
ErrorContext for preflight failures. |
Source code in src/marianne/healing/context.py
get_context_summary
¶
Get a summary of context for logging/display.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary with key context information. |
Source code in src/marianne/healing/context.py
HealingReport
dataclass
¶
HealingReport(error_context, diagnoses=list(), actions_taken=list(), actions_skipped=list(), diagnostic_outputs=list())
Report of a self-healing attempt.
Captures what was diagnosed, what actions were taken, and what issues remain for manual intervention.
Attributes¶
diagnoses
class-attribute
instance-attribute
¶
All diagnoses found by the engine.
actions_taken
class-attribute
instance-attribute
¶
(remedy_name, result) for each action attempted.
actions_skipped
class-attribute
instance-attribute
¶
(remedy_name, reason) for each skipped action.
diagnostic_outputs
class-attribute
instance-attribute
¶
(remedy_name, diagnostic_text) for guidance-only remedies.
any_remedies_applied
property
¶
Check if any remedies were successfully applied.
should_retry
property
¶
Whether a retry should be attempted after healing.
Returns True if any automatic remedies succeeded.
Functions¶
format
¶
Generate human-readable report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
verbose
|
bool
|
Include full diagnostic output. |
False
|
Returns:
| Type | Description |
|---|---|
str
|
Formatted healing report string. |
Source code in src/marianne/healing/coordinator.py
SelfHealingCoordinator
¶
SelfHealingCoordinator(registry, auto_confirm=False, dry_run=False, disabled_remedies=None, max_healing_attempts=2)
Orchestrates the self-healing process.
Takes an error context and coordinates: 1. Finding applicable remedies 2. Applying automatic remedies 3. Prompting for suggested remedies 4. Collecting diagnostic output
Example
registry = create_default_registry() coordinator = SelfHealingCoordinator(registry)
context = ErrorContext.from_execution_result(...) report = await coordinator.heal(context)
if report.should_retry: # Retry the sheet
Initialize the coordinator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
RemedyRegistry
|
Registry of available remedies. |
required |
auto_confirm
|
bool
|
Auto-approve suggested remedies (--yes flag). |
False
|
dry_run
|
bool
|
Show what would be done without changes. |
False
|
disabled_remedies
|
set[str] | None
|
Set of remedy names to skip. |
None
|
max_healing_attempts
|
int
|
Maximum healing cycles before giving up. |
2
|
Source code in src/marianne/healing/coordinator.py
Functions¶
heal
async
¶
Run the self-healing process.
- Find applicable remedies
- Apply automatic remedies
- Prompt for suggested remedies (unless auto_confirm)
- Display diagnostic output for manual-fix issues
- Return report of what was done
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context with diagnostic information. |
required |
Returns:
| Type | Description |
|---|---|
HealingReport
|
HealingReport with actions taken and results. |
Source code in src/marianne/healing/coordinator.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | |
reset
¶
Reset healing attempt counter.
Call this before starting a new healing cycle for a different error.
Diagnosis
dataclass
¶
Diagnosis(error_code, issue, explanation, suggestion, confidence, remedy_name=None, requires_confirmation=False, context=dict())
Result of analyzing an error.
Contains information about what went wrong and how to fix it. Multiple diagnoses may be returned for a single error, sorted by confidence (highest first).
Attributes:
| Name | Type | Description |
|---|---|---|
error_code |
str
|
The error code being diagnosed |
issue |
str
|
What went wrong (human-readable summary) |
explanation |
str
|
Why the error happened (detailed) |
suggestion |
str
|
How to fix it (actionable) |
confidence |
float
|
0.0-1.0, higher = more certain this diagnosis is correct |
remedy_name |
str | None
|
Name of the remedy that can fix this (if any) |
requires_confirmation |
bool
|
True for suggested remedies |
context |
dict[str, Any]
|
Extra data for the remedy to use |
Functions¶
format_short
¶
format_full
¶
Format with full details.
Source code in src/marianne/healing/diagnosis.py
DiagnosisEngine
¶
Diagnoses errors and suggests remedies.
Takes an ErrorContext and queries all registered remedies to find applicable diagnoses, returning them sorted by confidence (highest first).
Example
registry = create_default_registry() engine = DiagnosisEngine(registry)
context = ErrorContext.from_preflight_error(...) diagnoses = engine.diagnose(context)
for diagnosis in diagnoses: print(f"{diagnosis.issue}: {diagnosis.suggestion}")
Initialize the diagnosis engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
remedy_registry
|
RemedyRegistry
|
Registry containing available remedies. |
required |
Source code in src/marianne/healing/diagnosis.py
Functions¶
diagnose
¶
Analyze error and return possible diagnoses.
Queries all registered remedies and collects their diagnoses. Results are sorted by confidence (highest first).
If a remedy's diagnose() raises an exception, a zero-confidence
sentinel Diagnosis is appended with remedy_name set to the failing
remedy's class name and issue describing the failure. This ensures
callers can detect partial diagnosis results without a return-type change.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context with diagnostic information. |
required |
Returns:
| Type | Description |
|---|---|
list[Diagnosis]
|
List of Diagnosis objects, sorted by confidence descending. |
list[Diagnosis]
|
Empty list if no remedies apply. |
Source code in src/marianne/healing/diagnosis.py
get_primary_diagnosis
¶
Get the highest-confidence diagnosis.
Convenience method when you only care about the best match.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context. |
required |
Returns:
| Type | Description |
|---|---|
Diagnosis | None
|
Highest-confidence Diagnosis, or None if no remedies apply. |
Source code in src/marianne/healing/diagnosis.py
get_automatic_diagnoses
¶
Get diagnoses for automatic remedies only.
Filters to only diagnoses that can be auto-applied without user confirmation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context. |
required |
Returns:
| Type | Description |
|---|---|
list[Diagnosis]
|
List of diagnoses from AUTOMATIC remedies. |
Source code in src/marianne/healing/diagnosis.py
RemedyRegistry
¶
Registry of available remedies.
Maintains a list of remedy instances and provides methods to query them by name or find applicable remedies for a given error context.
Example
registry = RemedyRegistry() registry.register(CreateMissingWorkspaceRemedy())
Find by name¶
remedy = registry.get_by_name("create_missing_workspace")
Find all that apply to an error¶
applicable = registry.find_applicable(context)
Initialize an empty registry.
Source code in src/marianne/healing/registry.py
Functions¶
register
¶
Register a remedy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
remedy
|
Remedy
|
Remedy instance to register. |
required |
all_remedies
¶
Get all registered remedies.
Returns:
| Type | Description |
|---|---|
list[Remedy]
|
List of all registered remedy instances. |
get_by_name
¶
Get remedy by name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Unique remedy identifier. |
required |
Returns:
| Type | Description |
|---|---|
Remedy | None
|
Remedy if found, None otherwise. |
Source code in src/marianne/healing/registry.py
find_applicable
¶
Find all remedies that apply to the error.
Queries each registered remedy and collects those that return a diagnosis. Results are sorted by diagnosis confidence (highest first).
Remedy diagnosis crashes are logged and recorded in
self.diagnosis_errors so callers can report them
instead of showing misleading "NO ACTION NEEDED" messages.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context with diagnostic information. |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[Remedy, Diagnosis]]
|
List of (remedy, diagnosis) tuples sorted by confidence. |
Source code in src/marianne/healing/registry.py
count
¶
Get the number of registered remedies.
Returns:
| Type | Description |
|---|---|
int
|
Number of remedies in the registry. |
Remedy
¶
Bases: Protocol
Protocol for remediation actions.
Remedies diagnose specific error patterns and can optionally apply fixes. Each remedy must implement: - name: Unique identifier - category: AUTOMATIC, SUGGESTED, or DIAGNOSTIC - risk_level: LOW, MEDIUM, or HIGH - description: Human-readable explanation - diagnose(): Check if this remedy applies - preview(): Show what would change - apply(): Make the actual changes - rollback(): Undo changes if needed - generate_diagnostic(): Provide guidance for manual fix
Attributes¶
Functions¶
diagnose
¶
Check if this remedy applies to the error.
Returns Diagnosis if applicable, None otherwise. The diagnosis includes confidence score and fix suggestion.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context with diagnostic information. |
required |
Returns:
| Type | Description |
|---|---|
Diagnosis | None
|
Diagnosis if this remedy can help, None otherwise. |
Source code in src/marianne/healing/remedies/base.py
preview
¶
Show what would be changed without making changes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Human-readable description of planned changes. |
apply
¶
Apply the remedy.
Only called if diagnose() returned a Diagnosis and: - category == AUTOMATIC, or - category == SUGGESTED and user confirmed
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context. |
required |
Returns:
| Type | Description |
|---|---|
RemedyResult
|
Result with success status and details. |
Source code in src/marianne/healing/remedies/base.py
rollback
¶
Undo the remedy if possible.
Called if remedy was applied but subsequent validation failed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
RemedyResult
|
The result from apply(). |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if rollback succeeded, False otherwise. |
Source code in src/marianne/healing/remedies/base.py
generate_diagnostic
¶
Generate detailed diagnostic message.
Called for DIAGNOSTIC category, or when user declines SUGGESTED.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
context
|
ErrorContext
|
Error context. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Formatted guidance for manual fix. |
Source code in src/marianne/healing/remedies/base.py
RemedyCategory
¶
Bases: str, Enum
Determines how a remedy is applied.
AUTOMATIC: Applied without asking (safe, reversible operations) SUGGESTED: Requires user confirmation (modifies files) DIAGNOSTIC: Cannot auto-fix, provides guidance only
RemedyResult
dataclass
¶
RemedyResult(success, message, action_taken, rollback_command=None, created_paths=list(), modified_files=list(), backup_paths=list())
Result of applying a remedy.
Tracks what was done and how to undo it if needed.
Attributes¶
rollback_command
class-attribute
instance-attribute
¶
Shell command to undo the remedy (if possible).
created_paths
class-attribute
instance-attribute
¶
Paths that were created by the remedy.
modified_files
class-attribute
instance-attribute
¶
Files that were modified by the remedy.
backup_paths
class-attribute
instance-attribute
¶
Backup files created before modification.
Functions¶
RiskLevel
¶
Bases: str, Enum
Risk level of applying the remedy.
Used to inform users about the potential impact of the fix.
Functions¶
create_default_registry
¶
Create registry with all built-in remedies.
This is the primary factory for getting a fully-configured remedy registry. It registers:
Automatic remedies (safe, apply without confirmation): - CreateMissingWorkspaceRemedy - CreateMissingParentDirsRemedy - FixPathSeparatorsRemedy
Suggested remedies (require user confirmation): - SuggestJinjaFixRemedy
Diagnostic remedies (provide guidance only): - DiagnoseAuthErrorRemedy - DiagnoseMissingCLIRemedy
Returns:
| Type | Description |
|---|---|
RemedyRegistry
|
RemedyRegistry with all built-in remedies registered. |