feat: WP-0003 complete — LEVEL3 advanced features + error framework

Implements full LEVEL3 feature set: cross-references (xref.py), numbered
figures (figures.py), auto-diagrams (diagrams.py), bibliography/citations
(bibliography.py), LEVEL3 capability detection (level3.py), and structured
error/warning records (errors.py). Builder, importer, and differ updated for
LEVEL3 round-trip support. REST and MCP interfaces updated with structured
warning records. 259 tests passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 10:51:38 +00:00
parent 760047b82b
commit ac442ea41f
26 changed files with 3713 additions and 74 deletions

80
src/markidocx/errors.py Normal file
View File

@@ -0,0 +1,80 @@
"""Structured error and warning types for markidocx (FR-12011210)."""
from __future__ import annotations
from dataclasses import dataclass
from enum import StrEnum
from typing import Any
class Severity(StrEnum):
INFO = "info"
WARNING = "warning"
ERROR = "error"
class OutputState(StrEnum):
"""Lifecycle state of a build/import/workflow result (FR-1210)."""
FINAL = "final"
PARTIAL = "partial"
FALLBACK = "fallback"
DEGRADED = "degraded"
UNRESOLVED = "unresolved"
@dataclass
class WarningRecord:
"""Structured warning record (FR-1208).
severity: info | warning | error
reason: FR-code-aligned description
construct: the token/element that triggered the warning
"""
severity: str
reason: str
construct: str = ""
def to_dict(self) -> dict[str, Any]:
return {
"severity": self.severity,
"reason": self.reason,
"construct": self.construct,
}
def __str__(self) -> str:
if self.construct:
return f"[{self.severity}] {self.reason}: {self.construct}"
return f"[{self.severity}] {self.reason}"
@dataclass
class FailureRecord:
"""Structured failure record (FR-1209).
severity: info | warning | error
reason: FR-code-aligned description
construct: the element that caused the failure
"""
severity: str
reason: str
construct: str = ""
def to_dict(self) -> dict[str, Any]:
return {
"severity": self.severity,
"reason": self.reason,
"construct": self.construct,
}
def __str__(self) -> str:
if self.construct:
return f"[{self.severity}] {self.reason}: {self.construct}"
return f"[{self.severity}] {self.reason}"
def warning_records_to_strings(records: list[WarningRecord]) -> list[str]:
"""Convert a list of WarningRecords to plain strings (backward compat helper)."""
return [str(r) for r in records]