| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- from __future__ import annotations
- from dataclasses import replace
- import pytest
- from script_build_host.domain.errors import (
- LegacyCanonicalIdentityConflict,
- ProtocolViolation,
- )
- from script_build_host.domain.phase_three_artifacts import (
- RootDeliveryManifestV1,
- canonicalize_legacy_projection,
- )
- from script_build_host.domain.phase_two_artifacts import (
- ScriptElementV1,
- ScriptParagraphElementLinkV1,
- ScriptParagraphV1,
- StructuredScriptArtifactV1,
- )
- _DIGEST = "sha256:" + "a" * 64
- def _script(
- *,
- root_id: int = 10,
- child_id: int = 20,
- element_id: int = 30,
- child_description: str = "child body",
- ) -> StructuredScriptArtifactV1:
- return StructuredScriptArtifactV1(
- direction_ref="script-build://artifact-versions/1",
- input_closure_digest=_DIGEST,
- paragraphs=(
- ScriptParagraphV1(
- paragraph_id=root_id,
- paragraph_index=1,
- level=1,
- parent_id=None,
- name="root",
- content_range={"start": 0, "end": 10},
- description="root body",
- ),
- ScriptParagraphV1(
- paragraph_id=child_id,
- paragraph_index=2,
- level=2,
- parent_id=root_id,
- name="child",
- content_range={"start": 10, "end": 20},
- description=child_description,
- ),
- ),
- elements=(
- ScriptElementV1(
- element_id=element_id,
- name="hook",
- dimension_primary="形式",
- dimension_secondary="opening",
- topic_support={"score": 1},
- ),
- ),
- paragraph_element_links=(
- ScriptParagraphElementLinkV1(
- paragraph_id=child_id,
- element_id=element_id,
- ),
- ),
- source_artifact_refs=(),
- evidence_refs=(),
- acceptance_notes=(),
- )
- def test_legacy_canonical_digest_ignores_every_physical_identity() -> None:
- first = canonicalize_legacy_projection(_script(), direction="# D", summary="summary")
- second = canonicalize_legacy_projection(
- _script(root_id=101, child_id=202, element_id=303),
- direction="# D",
- summary="summary",
- )
- assert first.content_payload() == second.content_payload()
- assert first.canonical_sha256 == second.canonical_sha256
- def test_legacy_canonical_digest_changes_with_business_content() -> None:
- first = canonicalize_legacy_projection(_script(), direction="# D", summary="summary")
- changed_body = canonicalize_legacy_projection(
- _script(child_description="changed"), direction="# D", summary="summary"
- )
- changed_direction = canonicalize_legacy_projection(
- _script(), direction="# other", summary="summary"
- )
- assert first.canonical_sha256 != changed_body.canonical_sha256
- assert first.canonical_sha256 != changed_direction.canonical_sha256
- def test_legacy_canonical_rejects_parent_cycles_and_duplicate_natural_elements() -> None:
- cycle = replace(
- _script(),
- paragraphs=(
- ScriptParagraphV1(10, 1, 2, 20, "a", {}),
- ScriptParagraphV1(20, 2, 2, 10, "b", {}),
- ),
- )
- with pytest.raises(LegacyCanonicalIdentityConflict, match="cycle"):
- canonicalize_legacy_projection(cycle)
- duplicate_elements = replace(
- _script(),
- elements=(
- ScriptElementV1(30, "hook", "形式", "opening"),
- ScriptElementV1(31, "hook", "形式", "opening"),
- ),
- paragraph_element_links=(),
- )
- with pytest.raises(LegacyCanonicalIdentityConflict, match="duplicated"):
- canonicalize_legacy_projection(duplicate_elements)
- def test_root_delivery_manifest_is_strict_bounded_and_publishable() -> None:
- manifest = RootDeliveryManifestV1.from_payload(
- {
- "schema_version": "root-delivery-manifest/v1",
- "direction_ref": "script-build://artifact-versions/1",
- "candidate_portfolio_ref": "script-build://artifact-versions/2",
- "structured_script_ref": "script-build://artifact-versions/3",
- "input_closure_digest": _DIGEST,
- "legacy_projection_digest": _DIGEST,
- "build_summary": "ok",
- "blocking_defects": [],
- }
- ).with_digest()
- manifest.require_publishable()
- assert manifest.canonical_sha256.startswith("sha256:")
- with pytest.raises(ProtocolViolation, match="unknown fields"):
- RootDeliveryManifestV1.from_payload({**manifest.content_payload(), "unknown": True})
- with pytest.raises(ProtocolViolation, match="blocking defects"):
- replace(
- manifest, blocking_defects=("not ready",), canonical_sha256=""
- ).require_publishable()
- with pytest.raises(ProtocolViolation, match="2,000"):
- replace(manifest, build_summary="x" * 2_001, canonical_sha256="")
|