# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/what-structural-signals-indicate-a-retention-scoped-memory-write-has-silently-outlived-its-scope.md
# Remnant Warrant:    https://corpusfetch.com/c/what-structural-signals-indicate-a-retention-scoped-memory-write-has-silently-outlived-its-scope.warrant.json
# Markdown SHA-256:   b2ccddf378951af19fa5772929fb09e02408e63b633efd55486c0b3fc24ddf43
# Code AST SHA-256:   1ee8dcfda032175b0e856673c515631c0797f8c0db4fac6b03e9be6296d42e0b
# Verified Classes:   ScopedForgetUnverifiedError
# Defensive Guards:   2 fail-closed invariants (zero external deps)

class ScopedForgetUnverifiedError(RuntimeError):
    """Raised when a forget cannot be confirmed to cover all reachable scopes."""
    pass


def forget_and_verify(memory, record_id: str, content_probe: str,
                      candidate_scopes: list[str]) -> dict:
    """
    Forget a record and verify it is unreachable from every scope that
    could plausibly address it. Refuses to report success on partial deletion.
    """
    resp = memory.forget(record_id)

    # Signal 1: no artifact count means we cannot trust the scope of deletion.
    deleted_count = resp.get("deleted_count")
    if deleted_count is None:
        raise ScopedForgetUnverifiedError(
            f"forget({record_id!r}) returned no deleted_count; "
            f"deletion scope is unverified"
        )

    # Signal 2: probe every scope that could reach the content.
    leaks = []
    for scope in candidate_scopes:
        hits = memory.read(query=content_probe, scope=scope)
        if hits:
            leaks.append(scope)

    if leaks:
        raise ScopedForgetUnverifiedError(
            f"forget({record_id!r}) removed {deleted_count} artifact(s) "
            f"but content remains readable under scopes: {leaks}"
        )

    return {"record_id": record_id, "deleted_count": deleted_count,
            "scopes_verified": candidate_scopes}
