Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/topology-status.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 55 additions & 11 deletions polylogue/storage/sqlite/archive_tiers/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -3356,17 +3356,61 @@ def apply_raw_membership_classification(
f"ambiguous={classification.ambiguous_raw_ids!r}) "
f"persisted_session_raw={None if persisted_session is None else str(persisted_session[0])!r}"
)
# No byte-governance refusal here: this branch is only
# reachable when the head raw is a member of THIS
# cohort, and membership rows for a source-keyed raw
# only exist after a governance conversion decided it
# belongs to membership classification -- a still-set
# logical_source_key on raw_sessions is interrupted-
# pass ordering drift (the conversion's key-nulling
# had not committed when the pass died), not evidence
# of live byte-chain governance. Foreign byte heads
# never reach this branch: they yield in the
# chain-governed-head branch above.
# polylogue-miwv: #3211 removed a byte-governance
# refusal here on the theory that this branch is only
# reachable after a real governance conversion (a
# still-set logical_source_key being interrupted-pass
# drift, not live evidence). That premise is false for
# the accepted head specifically: ``_apply_membership_
# sessions`` (sources/live/batch.py) unconditionally
# injects the current ``raw_revision_heads`` accepted
# raw into the comparison cohort even when it has
# NEVER been through a membership conversion -- the
# #2718 scenario this whole code path exists for
# (a byte-governed head being compared against
# membership-discovered content for the first time).
# Content-prefix growth alone cannot prove the older
# bundle raw supersedes a head that still has live,
# unresolved byte-append evidence hanging off it (a
# quarantined/pending append raw whose
# ``predecessor_source_revision`` chains to the head's
# own ``source_revision``) that this classification
# pass never saw. Only matters when replay is about to
# CHANGE the accepted raw (mirrors #2718's original
# ``accepted_raw_id != existing_raw_id`` guard
# condition) -- a classification that keeps the same
# existing_raw_id as the accepted member (e.g. the
# head's own content already dominates every other
# cohort member) is a no-op re-affirmation, not a
# replacement, regardless of dangling evidence.
# Narrower than #2718's original blanket
# ``logical_source_key IS NOT NULL`` check so #3211's
# own interrupted-pass-drift resumption (no dangling
# append descendant, just a stale un-nulled key) is
# unaffected.
if accepted_raw_id != existing_raw_id:
classified_placeholders = ", ".join("?" for _ in classified_raw_ids) or "NULL"
dangling_append = conn.execute(
f"""
SELECT 1
FROM raw_sessions AS child
WHERE child.logical_source_key = ?
AND child.raw_id != ?
AND child.raw_id NOT IN ({classified_placeholders})
AND child.predecessor_source_revision IS NOT NULL
AND child.predecessor_source_revision = (
SELECT source_revision FROM raw_sessions WHERE raw_id = ?
)
LIMIT 1
""",
(logical_source_key, existing_raw_id, *classified_raw_ids, existing_raw_id),
).fetchone()
if dangling_append is not None:
raise RuntimeError(
"membership replay cannot replace a head with unresolved byte-append "
f"evidence: logical_source_key={logical_source_key!r} "
f"existing_head(raw_id={existing_raw_id!r})"
)
self._conn.execute(
"DELETE FROM raw_revision_heads WHERE logical_source_key = ?",
(logical_source_key,),
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/sources/test_live_batch_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -3811,6 +3811,31 @@ def test_bundle_replay_respects_unconvertible_single_session_head(
succeeds: bool,
census_head: bool,
) -> None:
"""Pins #2718's fail-closed contract: a bundle raw discovered later must
never silently replace an accepted head that still has live, unresolved
byte-append evidence (the QUARANTINED append raw this test binds), even
when the bundle's own content happens to strictly extend the head's
content (``bundle_texts2``/``bundle_texts3``: content-prefix growth alone
is not proof of provenance).

polylogue-miwv (2026-07-21): #3211 ("in-cohort head-retire drift fix")
removed ``apply_raw_membership_classification``'s byte-governance refusal
on the mistaken premise that its branch is only reachable after a real
membership-governance conversion -- but ``_apply_membership_sessions``
unconditionally injects the CURRENT accepted head into the comparison
cohort even when it has never been converted (exactly this test's byte-
governed-head scenario), so the removed guard's absence let the older
bundle's superset content silently move the head (message_count 2->3,
``accepted_raw_id`` changed) for ``bundle_texts2``/``bundle_texts3``.
This was not caused by, and is unrelated to, the messages_fts_identity
UNIQUE(block_id) ledger work landing the same day (polylogue-miwv's
other commits) -- confirmed by reproducing this exact failure on the
commit immediately preceding messages_fts_identity's introduction.
Restored as a narrower guard (refuses only when replay is about to change
the accepted raw AND a live raw_sessions row still chains a
``predecessor_source_revision`` off the existing head) so #3211's own
interrupted-pass-drift resumption keeps working.
"""
root = tmp_path / "sessions"
root.mkdir()
current = root / "current.jsonl"
Expand Down