feat(materialize): add §5 materialization with collision gate and replacement
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
This commit is contained in:
parent
c94ed6d525
commit
0ff946696c
5 changed files with 593 additions and 6 deletions
|
|
@ -75,9 +75,23 @@ def load_manifest(path: Path) -> Manifest:
|
|||
Raises ManifestError on any schema violation, before any source call.
|
||||
"""
|
||||
try:
|
||||
data: object = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, ValueError) as exc:
|
||||
raw = path.read_bytes()
|
||||
except OSError as exc:
|
||||
raise ManifestError(f"cannot read manifest {path}: {exc}") from exc
|
||||
return load_manifest_bytes(raw)
|
||||
|
||||
|
||||
def load_manifest_bytes(raw: bytes) -> Manifest:
|
||||
"""Fail-fast validate a manifest from its raw bytes (spec §4).
|
||||
|
||||
The bytes-level entry point exists so materialization can hash and parse
|
||||
the SAME bytes — the §5 provenance stamp must reference exactly the
|
||||
manifest version that produced the run.
|
||||
"""
|
||||
try:
|
||||
data: object = json.loads(raw.decode("utf-8"))
|
||||
except (UnicodeDecodeError, ValueError) as exc:
|
||||
raise ManifestError(f"manifest is not valid UTF-8 JSON: {exc}") from exc
|
||||
return _validate_manifest(data)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue