TDD step 5: materialize_bundle takes three explicit inputs (manifest, bundle dir, regex-validated ingested_at — no wall-clock default) and stages every extraction in memory before the first disk mutation. The §3 collision gate refuses to overwrite any file without the ingest stamp, before any mutation; replacement removes exactly the stamped set. Frontmatter is the seven §5 keys in spec order with whitespace collapse; output is LF-only raw bytes with one trailing newline; the provenance stamp hashes the same bytes that are parsed. Fresh index.md gets bundle_summary plus idempotent links in extraction order (§6 creation path; preserve/removal rules come next). The §8 network gate refuses http fail-fast without the per-run opt-in; the http transport itself lands in step 7. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QeqhJpYQyghASjiJo5EhGg
40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
"""Typed error hierarchy rooted in IngestError."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
class IngestError(Exception):
|
|
"""Base class for every error raised by this library."""
|
|
|
|
|
|
class ManifestError(IngestError):
|
|
"""The manifest failed fail-fast schema validation (ingest-spec §4)."""
|
|
|
|
|
|
class RenderError(IngestError):
|
|
"""A value cannot be rendered under the §5 body rules (never silent coercion)."""
|
|
|
|
|
|
class SourceError(IngestError):
|
|
"""An extraction failed against its source (ingest-spec §4, §8).
|
|
|
|
Covers fail-closed path-boundary violations, missing/malformed source
|
|
content, and max_rows cap violations — always typed, never a leaked
|
|
OSError and never silent truncation.
|
|
"""
|
|
|
|
|
|
class MaterializationError(IngestError):
|
|
"""Materialization refused or failed (ingest-spec §5).
|
|
|
|
Covers an invalid ingested_at argument and the §3 collision gate (a
|
|
generated name occupied by a file without the ingest stamp).
|
|
"""
|
|
|
|
|
|
class NetworkGateError(IngestError):
|
|
"""A network source was used without the per-run opt-in flag (spec §8).
|
|
|
|
Local-only default, no silent egress: the flag is a run argument — the
|
|
manifest cannot grant itself network access.
|
|
"""
|