Index: tests/test_id_lifecycle.py
===================================================================
--- tests/test_id_lifecycle.py	(revision e230c4058e9588cd8c4bb65512c19bdbdb5d076b)
+++ tests/test_id_lifecycle.py	(revision 68fdfc4e1e5bbc6a1f26d597e6934cef75f39358)
@@ -115,2 +115,47 @@
     with pytest.raises(RuntimeError, match="mark obsolete"):
         q.bump_version()
+
+def test_fork_creates_independent_domain(sample_domain):
+    original = sample_domain
+
+    forked = original.fork(domain_id="DST")
+
+    # ─── identity ───────────────────────────────────────────────────────
+    assert forked is not original
+    assert isinstance(forked.flexo_id, FlexOID)
+    assert forked.flexo_id != original.flexo_id
+
+    # ─── lifecycle reset ────────────────────────────────────────────────
+    assert forked.state == EntityState.DRAFT
+    assert forked.version == 1
+
+    # ─── provenance ─────────────────────────────────────────────────────
+    assert forked.origin == str(original.flexo_id)
+
+    # ─── domain reassigned ──────────────────────────────────────────────
+    assert forked.domain_id == "DST"
+
+def test_fork_does_not_mutate_original(sample_domain):
+    original = sample_domain
+    original_id = original.flexo_id
+    original_fp = original.fingerprint
+
+    _ = original.fork(domain_id="DST")
+
+    assert original.flexo_id == original_id
+    assert original.fingerprint == original_fp
+    assert original.origin is None
+
+def test_fork_does_not_shadow_state(sample_domain):
+    forked = sample_domain.fork(domain_id="DST")
+
+    # No instance attribute allowed
+    assert "state" not in forked.__dict__
+
+    # Property must still work
+    assert forked.state == EntityState.DRAFT
+
+def test_fork_without_origin(sample_domain):
+    forked = sample_domain.fork(domain_id="DST", keep_origin=False)
+
+    assert forked.origin is None
