Subject: [PATCH 17/21] wip: retain grouped publication effects

From: Justin Youens <[email-masked]>
Date: Sat, 15 Aug 2026 12:37:17 -0500

---
 src/backend/drm/TiledDRMIntegration.cpp   |  52 ++++
 src/backend/drm/TiledDRMIntegration.hpp   |  14 +
 src/backend/drm/TiledRuntime.hpp          |   6 +
 src/backend/drm/TiledRuntimeAuthority.cpp | 331 +++++++++++++++++++++-
 src/backend/drm/TiledRuntimeAuthority.hpp | 131 ++++++++-
 tests/TiledAtomic.cpp                     | 245 ++++++++++++++--
 tests/TiledDRMIntegration.cpp             |  27 ++
 tests/TiledRuntime.cpp                    |   3 +-
 8 files changed, 761 insertions(+), 48 deletions(-)

diff --git a/src/backend/drm/TiledDRMIntegration.cpp b/src/backend/drm/TiledDRMIntegration.cpp
index c834ccacfe25024955a4707c393e477fa4d7555f..5e668fe4854456ad0c6c6dea017f0dda8a1ec6ac 100644
--- a/src/backend/drm/TiledDRMIntegration.cpp
+++ b/src/backend/drm/TiledDRMIntegration.cpp
@@ -1012,6 +1012,50 @@ SGroupedTestModesetResult CTiledDRMIntegrationRegistry::executeCurrentGroupedTes
     return executeCurrentGroupedTestModesetKey(backend.impl_, expected, group, outputMode);
 }
 
+SGroupedInitialFrameResult CTiledDRMIntegrationRegistry::submitCurrentGroupedInitialFrameKey(const void* key, const POutputBridgeObservation& expected,
+                                                                                             const PScanGroupDefinition& group, const CSharedPointer<SOutputMode>& outputMode,
+                                                                                             const PGroupedPublicationInstance& publication,
+                                                                                             const CSharedPointer<CDRMFB>& framebuffer, const CSharedPointer<IBuffer>& buffer,
+                                                                                             uintptr_t transactionId, uint64_t deadlineNs) noexcept {
+    const auto THREAD = m_impl->registeredThread(key);
+    if (!THREAD || *THREAD != std::this_thread::get_id())
+        return {.status = eGroupedInitialFrameStatus::WRONG_THREAD};
+    if (!expected || !group || !outputMode || !publication || transactionId == 0 || deadlineNs == 0)
+        return {.status = eGroupedInitialFrameStatus::INVALID_CURRENT};
+    const auto ENTRY = m_impl->entries.find(key);
+    if (ENTRY == m_impl->entries.end() || ENTRY->second.detachBegun || !ENTRY->second.outputBridge || !ENTRY->second.groupedRuntime || !ENTRY->second.allocationShadow)
+        return {.status = eGroupedInitialFrameStatus::INVALID_CURRENT};
+    if (m_impl->mutationBusy(ENTRY->second))
+        return {.status = eGroupedInitialFrameStatus::BUSY};
+
+    const auto                 SHADOW = ENTRY->second.allocationShadow;
+    SGroupedInitialFrameResult result{.status = eGroupedInitialFrameStatus::INVALID_CURRENT};
+    bool                       bridgeCurrent = false;
+    bool                       invoked       = false;
+    try {
+        const auto ALLOCATION_CURRENT = withCurrentAllocationKey(key, SHADOW, [&](const CPlan&, const SCurrentState& current) {
+            const auto CURRENT_ENTRY = m_impl->entries.find(key);
+            if (CURRENT_ENTRY == m_impl->entries.end() || !CURRENT_ENTRY->second.outputBridge || !CURRENT_ENTRY->second.groupedRuntime)
+                return;
+            bridgeCurrent = CURRENT_ENTRY->second.outputBridge->withCurrentOwner(current, [&](const POutputBridgeObservation& observation) {
+                if (observation.impl_ != expected.impl_)
+                    return;
+                invoked = true;
+                result  = CURRENT_ENTRY->second.groupedRuntime->submitInitialCurrent(observation, group, outputMode, publication, framebuffer, buffer, transactionId, deadlineNs);
+            });
+        });
+        return ALLOCATION_CURRENT && bridgeCurrent && invoked ? result : SGroupedInitialFrameResult{.status = eGroupedInitialFrameStatus::INVALID_CURRENT};
+    } catch (...) { return {.status = eGroupedInitialFrameStatus::ALLOCATION_FAILED}; }
+}
+
+SGroupedInitialFrameResult CTiledDRMIntegrationRegistry::submitCurrentGroupedInitialFrame(const CWeakPointer<CDRMBackend>& backend, const POutputBridgeObservation& expected,
+                                                                                          const PScanGroupDefinition& group, const CSharedPointer<SOutputMode>& outputMode,
+                                                                                          const PGroupedPublicationInstance& publication, const CSharedPointer<CDRMFB>& framebuffer,
+                                                                                          const CSharedPointer<IBuffer>& buffer, uintptr_t transactionId,
+                                                                                          uint64_t deadlineNs) noexcept {
+    return submitCurrentGroupedInitialFrameKey(backend.impl_, expected, group, outputMode, publication, framebuffer, buffer, transactionId, deadlineNs);
+}
+
 SOrdinaryKMSGateResult CTiledDRMIntegrationRegistry::gateOrdinaryKMSKey(const void* key, const CWeakPointer<CDRMBackend>& backend, std::span<const SOrdinaryKMSCRTC> crtcs,
                                                                         const std::function<bool()>& callback) noexcept {
     const auto THREAD = m_impl->registeredThread(key);
@@ -1093,6 +1137,14 @@ SGroupedTestModesetResult CTiledDRMIntegrationRegistry::executeCurrentTestModese
     return executeCurrentGroupedTestModesetKey(lifetime.impl_, expected, group, outputMode);
 }
 
+SGroupedInitialFrameResult CTiledDRMIntegrationRegistry::submitCurrentTestInitialFrame(const PBackendLifetime& lifetime, const POutputBridgeObservation& expected,
+                                                                                       const PScanGroupDefinition& group, const CSharedPointer<SOutputMode>& outputMode,
+                                                                                       const PGroupedPublicationInstance& publication, const CSharedPointer<CDRMFB>& framebuffer,
+                                                                                       const CSharedPointer<IBuffer>& buffer, uintptr_t transactionId,
+                                                                                       uint64_t deadlineNs) noexcept {
+    return submitCurrentGroupedInitialFrameKey(lifetime.impl_, expected, group, outputMode, publication, framebuffer, buffer, transactionId, deadlineNs);
+}
+
 eSessionResult CTiledDRMIntegrationRegistry::rotateSessionKey(const void* key) noexcept {
     const auto THREAD = m_impl->registeredThread(key);
     if (!THREAD)
diff --git a/src/backend/drm/TiledDRMIntegration.hpp b/src/backend/drm/TiledDRMIntegration.hpp
index 874aa7a12a96b8f03f546aa47d51fb2e012b2f13..9b50451d93927b88c7b46962f8a906483ff350e2 100644
--- a/src/backend/drm/TiledDRMIntegration.hpp
+++ b/src/backend/drm/TiledDRMIntegration.hpp
@@ -35,7 +35,9 @@ namespace Aquamarine::NDRM::NTiledDRMIntegration { // NOLINT(readability-identif
     using NTiledRuntimeAuthority::SOrdinaryKMSCRTC;
     using NTiledRuntimeAuthority::SOrdinaryKMSGateResult;
     using NTiledRuntimeAuthority::SGroupedPageFlipResult;
+    using NTiledRuntimeAuthority::SGroupedInitialFrameResult;
     using NTiledRuntimeAuthority::SGroupedTestModesetResult;
+    using NTiledRuntimeAuthority::PGroupedPublicationInstance;
     using NTiledScan::PCommittedScan;
     using NTiledScan::PScanGroupDefinition;
     using NTiledScan::PPreparedScan;
@@ -239,6 +241,10 @@ namespace Aquamarine::NDRM::NTiledDRMIntegration { // NOLINT(readability-identif
                                                                         const std::function<void(const POutputBridgeObservation&)>& callback) noexcept;
         [[nodiscard]] SGroupedTestModesetResult executeCurrentGroupedTestModeset(const CWeakPointer<CDRMBackend>& backend, const POutputBridgeObservation& expected,
                                                                                  const PScanGroupDefinition& group, const CSharedPointer<SOutputMode>& outputMode) noexcept;
+        [[nodiscard]] SGroupedInitialFrameResult submitCurrentGroupedInitialFrame(const CWeakPointer<CDRMBackend>& backend, const POutputBridgeObservation& expected,
+                                                                                  const PScanGroupDefinition& group, const CSharedPointer<SOutputMode>& outputMode,
+                                                                                  const PGroupedPublicationInstance& publication, const CSharedPointer<CDRMFB>& framebuffer,
+                                                                                  const CSharedPointer<IBuffer>& buffer, uintptr_t transactionId, uint64_t deadlineNs) noexcept;
         [[nodiscard]] SOrdinaryKMSGateResult    gateOrdinaryKMS(const CWeakPointer<CDRMBackend>& backend, std::span<const SOrdinaryKMSCRTC> crtcs,
                                                                 const std::function<bool()>& callback) noexcept;
         [[nodiscard]] SGroupedPageFlipResult    routeGroupedPageFlip(const CWeakPointer<CDRMBackend>& backend, uintptr_t transactionId, uint32_t crtcId, uint32_t sequence,
@@ -275,6 +281,10 @@ namespace Aquamarine::NDRM::NTiledDRMIntegration { // NOLINT(readability-identif
                                                                            const std::function<void(const POutputBridgeObservation&)>& callback) noexcept;
         [[nodiscard]] SGroupedTestModesetResult executeCurrentGroupedTestModesetKey(const void* key, const POutputBridgeObservation& expected, const PScanGroupDefinition& group,
                                                                                     const CSharedPointer<SOutputMode>& outputMode) noexcept;
+        [[nodiscard]] SGroupedInitialFrameResult submitCurrentGroupedInitialFrameKey(const void* key, const POutputBridgeObservation& expected, const PScanGroupDefinition& group,
+                                                                                     const CSharedPointer<SOutputMode>& outputMode, const PGroupedPublicationInstance& publication,
+                                                                                     const CSharedPointer<CDRMFB>& framebuffer, const CSharedPointer<IBuffer>& buffer,
+                                                                                     uintptr_t transactionId, uint64_t deadlineNs) noexcept;
         [[nodiscard]] SOrdinaryKMSGateResult    gateOrdinaryKMSKey(const void* key, const CWeakPointer<CDRMBackend>& backend, std::span<const SOrdinaryKMSCRTC> crtcs,
                                                                    const std::function<bool()>& callback) noexcept;
         [[nodiscard]] SGroupedPageFlipResult routeGroupedPageFlipKey(const void* key, uintptr_t transactionId, uint32_t crtcId, uint32_t sequence, uint64_t timestampNs) noexcept;
@@ -300,6 +310,10 @@ namespace Aquamarine::NDRM::NTiledDRMIntegration { // NOLINT(readability-identif
                                                         const CSharedPointer<IGroupedTestFramebufferSource>& framebufferSource) noexcept;
         [[nodiscard]] SGroupedTestModesetResult executeCurrentTestModeset(const PBackendLifetime& lifetime, const POutputBridgeObservation& expected,
                                                                           const PScanGroupDefinition& group, const CSharedPointer<SOutputMode>& outputMode) noexcept;
+        [[nodiscard]] SGroupedInitialFrameResult submitCurrentTestInitialFrame(const PBackendLifetime& lifetime, const POutputBridgeObservation& expected,
+                                                                               const PScanGroupDefinition& group, const CSharedPointer<SOutputMode>& outputMode,
+                                                                               const PGroupedPublicationInstance& publication, const CSharedPointer<CDRMFB>& framebuffer,
+                                                                               const CSharedPointer<IBuffer>& buffer, uintptr_t transactionId, uint64_t deadlineNs) noexcept;
         [[nodiscard]] bool                      exhaustTestResourceEpoch(const PBackendLifetime& lifetime) noexcept;
 
         class CImpl;
diff --git a/src/backend/drm/TiledRuntime.hpp b/src/backend/drm/TiledRuntime.hpp
index 16cbc69088009e16b47f16d89b053221c4d33f50..b3b8f2ed4d1dff773955335d4a8e49900fe91d39 100644
--- a/src/backend/drm/TiledRuntime.hpp
+++ b/src/backend/drm/TiledRuntime.hpp
@@ -638,6 +638,12 @@ namespace Aquamarine::NDRM { // NOLINT(readability-identifier-naming): establish
             // allocation into currentFrames before the noexcept emplace.
             m_lastFrames.clear();
             m_lastFrames.swap(m_currentFrames);
+            // The backendRelease effect now owns every displaced buffer until
+            // its consumer runs. Retain only the exact framebuffer owners in
+            // lastFrames: keeping a second buffer owner here would make a
+            // successfully consumed release unable to relinquish that buffer.
+            for (auto& LAST : m_lastFrames)
+                LAST.bufferOwner = {};
             m_currentFrames.emplace_back(std::move(m_prepared->frame));
             m_completedTransaction = transactionId;
             m_prepared.reset();
diff --git a/src/backend/drm/TiledRuntimeAuthority.cpp b/src/backend/drm/TiledRuntimeAuthority.cpp
index 9e786dabaa72052b16ff22bb302b56c9f054fffa..0410f208731d4bcf51241ed8828fdbadd3eab360 100644
--- a/src/backend/drm/TiledRuntimeAuthority.cpp
+++ b/src/backend/drm/TiledRuntimeAuthority.cpp
@@ -3,7 +3,9 @@
 #include "PlaneFormats.hpp"
 
 #include <algorithm>
+#include <cmath>
 #include <exception>
+#include <limits>
 #include <ranges>
 #include <utility>
 
@@ -104,13 +106,22 @@ namespace {
     }
 }
 
-CGroupedFrameOwner::CGroupedFrameOwner(PResolvedTiledAtomicRoute route, CSharedPointer<CDRMFB> framebuffer, CSharedPointer<IBuffer> buffer) noexcept :
-    m_route(std::move(route)), m_framebuffer(std::move(framebuffer)), m_buffer(std::move(buffer)) {}
+CGroupedFrameOwner::CGroupedFrameOwner(eGroupedFrameOwnerRole role, PResolvedTiledAtomicRoute route, PGroupedPublicationInstance publication, CSharedPointer<CDRMFB> framebuffer,
+                                       CSharedPointer<IBuffer> buffer) noexcept :
+    m_role(role), m_route(std::move(route)), m_publication(std::move(publication)), m_framebuffer(std::move(framebuffer)), m_buffer(std::move(buffer)) {}
+
+eGroupedFrameOwnerRole CGroupedFrameOwner::role() const noexcept {
+    return m_role;
+}
 
 const PResolvedTiledAtomicRoute& CGroupedFrameOwner::route() const noexcept {
     return m_route;
 }
 
+const PGroupedPublicationInstance& CGroupedFrameOwner::publication() const noexcept {
+    return m_publication;
+}
+
 const CSharedPointer<CDRMFB>& CGroupedFrameOwner::framebuffer() const noexcept {
     return m_framebuffer;
 }
@@ -133,10 +144,87 @@ const CSharedPointer<const CGroupedFrameOwner>& PGroupedFrameOwner::owner() cons
     return m_owner;
 }
 
+CGroupedPublicationInstance::CGroupedPublicationInstance(POutputDefinitionIdentity identity, CSharedPointer<IGroupedPublicationEffectSink> sink) noexcept :
+    m_identity(std::move(identity)), m_sink(std::move(sink)) {}
+
+PGroupedPublicationInstance CGroupedPublicationInstance::create(const POutputDefinitionIdentity& identity, const CSharedPointer<IGroupedPublicationEffectSink>& sink) noexcept {
+    if (!identity || !sink)
+        return {};
+    try {
+        return PGroupedPublicationInstance{new CGroupedPublicationInstance{identity, sink}};
+    } catch (...) { return {}; }
+}
+
+const POutputDefinitionIdentity& CGroupedPublicationInstance::definitionIdentity() const noexcept {
+    return m_identity;
+}
+
+bool CGroupedPublicationInstance::arm(uintptr_t transactionId) noexcept {
+    if (m_effectActive || transactionId == 0 || m_transactionId != 0 || m_accepted || m_schedulerPending || !m_identity || !m_sink)
+        return false;
+    m_transactionId = transactionId;
+    return true;
+}
+
+bool CGroupedPublicationInstance::rollback(uintptr_t transactionId) noexcept {
+    if (m_effectActive || transactionId == 0 || transactionId != m_transactionId || m_accepted || m_schedulerPending)
+        return false;
+    m_transactionId = 0;
+    return true;
+}
+
+bool CGroupedPublicationInstance::accept(uintptr_t transactionId, bool schedulerSubmit) noexcept {
+    if (m_effectActive || transactionId == 0 || transactionId != m_transactionId || m_accepted || m_schedulerPending || !m_sink)
+        return false;
+
+    m_accepted         = true;
+    m_schedulerPending = schedulerSubmit;
+    if (!schedulerSubmit)
+        return true;
+
+    m_effectActive = true;
+    Hyprutils::Utils::CScopeGuard effectGuard([&] { m_effectActive = false; });
+    m_sink->frameSubmitted(transactionId);
+    return true;
+}
+
+eGroupedCompletionConsumeResult CGroupedPublicationInstance::consumeCompletion(const PGroupedPublicationInstance& completingPublication, uintptr_t transactionId,
+                                                                               const PResolvedTiledAtomicRoute& acceptedRoute, const CGroupedRuntime::SEffects& effects) noexcept {
+    if (m_effectActive)
+        return eGroupedCompletionConsumeResult::BUSY;
+    if (!m_accepted || !m_schedulerPending || m_transactionId == 0)
+        return eGroupedCompletionConsumeResult::NOT_ACCEPTED;
+    if (transactionId == 0 || transactionId != m_transactionId)
+        return eGroupedCompletionConsumeResult::STALE_TOKEN;
+    if (!completingPublication || completingPublication.get() != this || !acceptedRoute || !sameOwner(acceptedRoute->definitionIdentity(), m_identity) ||
+        effects.disposition != eTiledEventDisposition::COMPLETED || !effects.schedulerComplete || !effects.present || !effects.presentation ||
+        effects.presentation->transactionId != transactionId)
+        return eGroupedCompletionConsumeResult::INVALID_EFFECTS;
+    for (const auto& RELEASE : effects.releases) {
+        const auto* OWNER = RELEASE.owner.get();
+        if (RELEASE.bufferId == 0 || !OWNER || OWNER->role() != eGroupedFrameOwnerRole::BUFFER || !OWNER->route() || !OWNER->publication() || !OWNER->buffer() ||
+            !sameOwner(OWNER->route()->definitionIdentity(), m_identity) || !sameOwner(OWNER->publication(), completingPublication))
+            return eGroupedCompletionConsumeResult::INVALID_EFFECTS;
+    }
+
+    const auto PRESENTATION = *effects.presentation;
+    m_transactionId         = 0;
+    m_accepted              = false;
+    m_schedulerPending      = false;
+    m_effectActive          = true;
+    Hyprutils::Utils::CScopeGuard effectGuard([&] { m_effectActive = false; });
+    m_sink->frameCompleted(acceptedRoute, PRESENTATION, effects.releases);
+    return eGroupedCompletionConsumeResult::DELIVERED;
+}
+
 SGroupedReconcileResult::operator bool() const noexcept {
     return result == eGroupedReconcileResult::RECONCILED || result == eGroupedReconcileResult::RECONCILED_WITH_QUIESCE;
 }
 
+SGroupedInitialFrameResult::operator bool() const noexcept {
+    return status == eGroupedInitialFrameStatus::ACCEPTED;
+}
+
 SOrdinaryKMSGateResult::operator bool() const noexcept {
     return status == eOrdinaryKMSGateStatus::EXECUTED;
 }
@@ -358,6 +446,148 @@ SGroupedTestModesetResult CGroupedRuntimeAuthority::executeCurrentTestModeset(co
     } catch (...) { return {.status = eGroupedTestModesetStatus::ALLOCATION_FAILED}; }
 }
 
+SGroupedInitialFrameResult CGroupedRuntimeAuthority::submitInitialCurrent(const POutputBridgeObservation& current, const PScanGroupDefinition& group,
+                                                                          const CSharedPointer<SOutputMode>& outputMode, const PGroupedPublicationInstance& publication,
+                                                                          const CSharedPointer<CDRMFB>& framebuffer, const CSharedPointer<IBuffer>& buffer, uintptr_t transactionId,
+                                                                          uint64_t deadlineNs) noexcept {
+    if (!onEventThread())
+        return {.status = eGroupedInitialFrameStatus::WRONG_THREAD};
+    if (m_mutationActive)
+        return {.status = eGroupedInitialFrameStatus::BUSY};
+    if (m_terminal)
+        return {.status = eGroupedInitialFrameStatus::TERMINAL};
+    if (!m_testDevice || m_testDrmFD < 0 || !m_testOperations || !m_testCleanupRegistry || m_testCleanupRegistry->drmFD() != m_testDrmFD)
+        return {.status = eGroupedInitialFrameStatus::NOT_CONFIGURED};
+    if (!current || !group || !outputMode || transactionId == 0 || deadlineNs == 0)
+        return {.status = eGroupedInitialFrameStatus::INVALID_CURRENT};
+    if (!publication)
+        return {.status = eGroupedInitialFrameStatus::INVALID_PUBLICATION};
+    if (!framebuffer || !buffer)
+        return {.status = eGroupedInitialFrameStatus::INVALID_FRAMEBUFFER};
+
+    m_mutationActive = true;
+    Hyprutils::Utils::CScopeGuard mutationGuard([&] { m_mutationActive = false; });
+    try {
+        const auto& SNAPSHOT = current->capturedSnapshot();
+        const auto* GROUP    = current->findGroup(group);
+        const auto  LIFETIME = m_testDevice->backend().lock();
+        const auto  BACKEND  = m_testBackend.lock();
+        if (!SNAPSHOT || !sameOwner(SNAPSHOT->device(), m_testDevice) || !GROUP || !sameOwner(GROUP->scanDefinition(), group) ||
+            GROUP->projection() != eGroupProjection::MULTI_STREAM_ALLOCATED || !GROUP->definitionIdentity() ||
+            !sameOwner(publication->definitionIdentity(), GROUP->definitionIdentity()) || !LIFETIME || LIFETIME->binding() != eBackendBinding::PRODUCTION_BACKEND || !BACKEND ||
+            BACKEND->drmFD() != m_testDrmFD || LIFETIME->drmBackend().impl_ != m_testBackend.impl_)
+            return {.status = eGroupedInitialFrameStatus::INVALID_CURRENT};
+
+        const auto FRAMEBUFFER_BUFFER = framebuffer->buffer.lock();
+        if (framebuffer->id == 0 || framebuffer->dead || framebuffer->backend.impl_ != m_testBackend.impl_ || !sameOwner(FRAMEBUFFER_BUFFER, buffer) || buffer->lockedByBackend)
+            return {.status = eGroupedInitialFrameStatus::INVALID_FRAMEBUFFER};
+        const auto ATTRS = buffer->dmabuf();
+        if (!ATTRS.success || ATTRS.format == DRM_FORMAT_INVALID || ATTRS.size.x <= 0 || ATTRS.size.y <= 0 ||
+            ATTRS.size.x > static_cast<double>(std::numeric_limits<uint32_t>::max()) || ATTRS.size.y > static_cast<double>(std::numeric_limits<uint32_t>::max()) ||
+            std::trunc(ATTRS.size.x) != ATTRS.size.x || std::trunc(ATTRS.size.y) != ATTRS.size.y)
+            return {.status = eGroupedInitialFrameStatus::INVALID_FRAMEBUFFER};
+
+        SGroupedInitialFrameResult result;
+        result.cleanup = m_testCleanupRegistry->retryPending();
+        if (!result.cleanup.complete()) {
+            result.status = eGroupedInitialFrameStatus::CLEANUP_PENDING;
+            return result;
+        }
+
+        const STiledAtomicFramebuffer ATOMIC_FRAMEBUFFER{
+            .id       = framebuffer->id,
+            .size     = {.width = static_cast<uint32_t>(ATTRS.size.x), .height = static_cast<uint32_t>(ATTRS.size.y)},
+            .format   = ATTRS.format,
+            .modifier = ATTRS.modifier,
+        };
+        const auto RESOLVED = resolveCapturedTiledAtomic({
+            .generationOwner    = current,
+            .groupDefinition    = group,
+            .definitionIdentity = GROUP->definitionIdentity(),
+            .outputMode         = outputMode,
+            .framebuffer        = ATOMIC_FRAMEBUFFER,
+        });
+        result.routeError   = RESOLVED.error;
+        if (!RESOLVED) {
+            result.status = eGroupedInitialFrameStatus::ROUTE_INVALID;
+            return result;
+        }
+
+        result.stageResult = stageRecord(current, RESOLVED.route);
+        auto* const RECORD = recordFor(GROUP->definitionIdentity());
+        if (!RECORD || !RECORD->runtime || !RECORD->activeRoute || !synchronizeRoute(*RECORD)) {
+            result.status = eGroupedInitialFrameStatus::RUNTIME_STAGE_FAILED;
+            return result;
+        }
+        if (RECORD->runtime->state() == eTiledRuntimeState::STAGED && !RECORD->runtime->publishDisabled()) {
+            result.status = eGroupedInitialFrameStatus::RUNTIME_STAGE_FAILED;
+            return result;
+        }
+        if (RECORD->runtime->state() != eTiledRuntimeState::PUBLISHED_DISABLED || RECORD->runtime->preparedRoute() || !RECORD->runtime->currentFrames().empty() ||
+            !RESOLVED.route->matchesRuntimePlan(RECORD->runtime->activePlan())) {
+            result.status = eGroupedInitialFrameStatus::RUNTIME_STAGE_FAILED;
+            return result;
+        }
+        RECORD->activeRoute = RESOLVED.route;
+
+        const auto BUILT    = buildTiledModesetRequest(RESOLVED.route, m_testDrmFD, m_testOperations, m_testCleanupRegistry);
+        result.requestError = BUILT.error;
+        if (!BUILT) {
+            result.cleanup = BUILT.cleanup;
+            result.status  = result.cleanup.complete() ? eGroupedInitialFrameStatus::REQUEST_BUILD_FAILED : eGroupedInitialFrameStatus::CLEANUP_PENDING;
+            return result;
+        }
+
+        const auto MAKE_OWNER = [&](eGroupedFrameOwnerRole role, const CSharedPointer<CDRMFB>& retainedFramebuffer,
+                                    const CSharedPointer<IBuffer>& retainedBuffer) -> PGroupedFrameOwner {
+            CSharedPointer<CGroupedFrameOwner>       mutableOwner{new CGroupedFrameOwner{role, RESOLVED.route, publication, retainedFramebuffer, retainedBuffer}};
+            CSharedPointer<const CGroupedFrameOwner> retained = mutableOwner;
+            return PGroupedFrameOwner{std::move(retained)};
+        };
+        const auto FRAMEBUFFER_OWNER = MAKE_OWNER(eGroupedFrameOwnerRole::FRAMEBUFFER, framebuffer, {});
+        const auto BUFFER_OWNER      = MAKE_OWNER(eGroupedFrameOwnerRole::BUFFER, {}, buffer);
+        const auto BUFFER_ID         = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(buffer.impl_));
+        if (!FRAMEBUFFER_OWNER || !BUFFER_OWNER || BUFFER_ID == 0 || !publication->arm(transactionId)) {
+            result.cleanup = BUILT.prepared->cleanup();
+            result.status  = eGroupedInitialFrameStatus::INVALID_PUBLICATION;
+            return result;
+        }
+
+        auto       transaction  = submitInitialTiledFrameTransaction(BUILT.prepared, *RECORD->runtime, m_reservations,
+                                                                     {
+                                                                         .framebufferId    = framebuffer->id,
+                                                                         .bufferId         = BUFFER_ID,
+                                                                         .framebufferOwner = FRAMEBUFFER_OWNER,
+                                                                         .bufferOwner      = BUFFER_OWNER,
+                                                                     },
+                                                                     transactionId, deadlineNs, m_testDrmFD);
+        const bool KMS_ACCEPTED = transaction.effects.kmsAccepted;
+        if (!KMS_ACCEPTED) {
+            static_cast<void>(publication->rollback(transactionId));
+            result.transaction = transaction;
+            result.cleanup     = BUILT.prepared->cleanup();
+            result.status      = eGroupedInitialFrameStatus::TRANSACTION_FAILED;
+            return result;
+        }
+
+        buffer->lockedByBackend         = true;
+        result.bufferLocked             = true;
+        const bool PUBLICATION_ACCEPTED = publication->accept(transactionId, transaction.effects.runtimeAccept.schedulerSubmit);
+        result.submitEffectDelivered    = PUBLICATION_ACCEPTED && transaction.effects.runtimeAccept.schedulerSubmit;
+        if (!PUBLICATION_ACCEPTED) {
+            const auto EFFECTS = RECORD->runtime->quiesce(eTiledQuiesceReason::EVENT_INVARIANT);
+            static_cast<void>(applyReservationEffects(EFFECTS));
+        }
+
+        const auto TRANSACTION_STATUS = transaction.status;
+        result.transaction            = transaction;
+        result.cleanup                = BUILT.prepared->cleanup();
+        result.status                 = PUBLICATION_ACCEPTED && TRANSACTION_STATUS == eTiledFrameTransactionStatus::ACCEPTED ? eGroupedInitialFrameStatus::ACCEPTED :
+                                                                                                                               eGroupedInitialFrameStatus::ACCEPTED_INVARIANT_FAILURE;
+        return result;
+    } catch (...) { return {.status = eGroupedInitialFrameStatus::ALLOCATION_FAILED}; }
+}
+
 bool CGroupedRuntimeAuthority::prepareTestModesetDetach() noexcept {
     if (!onEventThread() || m_mutationActive)
         return false;
@@ -393,6 +623,34 @@ bool CGroupedRuntimeAuthority::synchronizeRoute(SRuntimeRecord& record) noexcept
     return true;
 }
 
+eGroupedCompletionConsumeResult CGroupedRuntimeAuthority::consumeCompletionDebt(SRuntimeRecord& record, SGroupedPageFlipResult& result) noexcept {
+    if (!record.completionDebt)
+        return eGroupedCompletionConsumeResult::NOT_ACCEPTED;
+
+    auto& DEBT                 = *record.completionDebt;
+    result.claimed             = true;
+    result.definitionIdentity  = DEBT.acceptedRoute ? DEBT.acceptedRoute->definitionIdentity() : record.identity;
+    result.route               = DEBT.acceptedRoute;
+    result.publication         = DEBT.publication;
+    result.reservationRetired  = DEBT.reservationRetired;
+    result.successorAdopted    = DEBT.successorAdopted;
+    result.successorGeneration = DEBT.successorGeneration;
+
+    if (DEBT.transactionId == 0 || !DEBT.acceptedRoute || !DEBT.publication)
+        return eGroupedCompletionConsumeResult::INVALID_EFFECTS;
+
+    const auto RELEASE_COUNT = DEBT.effects.releases.size();
+    const auto CONSUMED      = DEBT.publication->consumeCompletion(DEBT.publication, DEBT.transactionId, DEBT.acceptedRoute, DEBT.effects);
+    if (CONSUMED != eGroupedCompletionConsumeResult::DELIVERED)
+        return CONSUMED;
+
+    result.completionDelivered = true;
+    result.releasesDelivered   = RELEASE_COUNT;
+    DEBT.effects.releases.clear();
+    record.completionDebt.reset();
+    return eGroupedCompletionConsumeResult::DELIVERED;
+}
+
 eGroupedStageResult CGroupedRuntimeAuthority::stageRecord(const POutputBridgeObservation& current, const PResolvedTiledAtomicRoute& route) {
     if (!exactCurrentRoute(current, route))
         return current && route && !sameOwner(current, route->generationOwner()) ? eGroupedStageResult::FOREIGN_ROUTE : eGroupedStageResult::INVALID_CURRENT;
@@ -409,7 +667,7 @@ eGroupedStageResult CGroupedRuntimeAuthority::stageRecord(const POutputBridgeObs
             }
 
             auto effects = ITERATOR->second.runtime->quiesce(eTiledQuiesceReason::INVALID_TOPOLOGY);
-            if (!applyReservationEffects(effects) || !ITERATOR->second.runtime->readyForDestruction())
+            if (!applyReservationEffects(effects) || ITERATOR->second.completionDebt || !ITERATOR->second.runtime->readyForDestruction())
                 return eGroupedStageResult::GROUP_CONFLICT;
             ITERATOR = m_runtimes.erase(ITERATOR);
         }
@@ -581,7 +839,7 @@ SGroupedQuiesceResult CGroupedRuntimeAuthority::quiesceAll(eTiledQuiesceReason r
 
 SGroupedRetirementResult CGroupedRuntimeAuthority::retireUnguarded(SRuntimeRecord& record, eTiledRetirementProof proof) {
     SGroupedRetirementResult result;
-    if (!record.runtime)
+    if (!record.runtime || record.completionDebt)
         return {.invariantFailed = true};
 
     auto retired   = record.runtime->retire(proof);
@@ -694,8 +952,24 @@ SGroupedPageFlipResult CGroupedRuntimeAuthority::routePageFlip(uintptr_t transac
         return {};
     if (ROUTE == eTiledRouteEventResult::RESERVED)
         return {.claimed = true, .disposition = eGroupedPageFlipDisposition::RESERVED};
-    if (ROUTE == eTiledRouteEventResult::STALE_TOKEN)
-        return {.claimed = true, .disposition = eGroupedPageFlipDisposition::STALE};
+    if (ROUTE == eTiledRouteEventResult::STALE_TOKEN) {
+        SRuntimeRecord* DEBT_OWNER = nullptr;
+        for (auto& [KEY, RECORD] : m_runtimes) {
+            static_cast<void>(KEY);
+            if (!RECORD.completionDebt || RECORD.completionDebt->transactionId != transactionId)
+                continue;
+            if (DEBT_OWNER)
+                return {.claimed = true, .disposition = eGroupedPageFlipDisposition::INVARIANT_FAILURE};
+            DEBT_OWNER = &RECORD;
+        }
+        if (!DEBT_OWNER)
+            return {.claimed = true, .disposition = eGroupedPageFlipDisposition::STALE};
+
+        SGroupedPageFlipResult result{.claimed = true, .disposition = eGroupedPageFlipDisposition::INVARIANT_FAILURE};
+        if (consumeCompletionDebt(*DEBT_OWNER, result) == eGroupedCompletionConsumeResult::DELIVERED)
+            result.disposition = eGroupedPageFlipDisposition::COMPLETED;
+        return result;
+    }
 
     SRuntimeRecord* OWNER = nullptr;
     for (auto& [KEY, RECORD] : m_runtimes) {
@@ -714,18 +988,18 @@ SGroupedPageFlipResult CGroupedRuntimeAuthority::routePageFlip(uintptr_t transac
     }
     if (!OWNER)
         return {.claimed = true, .disposition = eGroupedPageFlipDisposition::INVARIANT_FAILURE};
+    if (OWNER->completionDebt)
+        return {.claimed = true, .disposition = eGroupedPageFlipDisposition::INVARIANT_FAILURE};
 
     if (ROUTE == eTiledRouteEventResult::UNEXPECTED_CRTC) {
         auto effects = OWNER->runtime->quiesce(eTiledQuiesceReason::EVENT_INVARIANT);
         static_cast<void>(applyReservationEffects(effects));
-        SGroupedPageFlipResult result{
+        return {
             .claimed            = true,
             .disposition        = eGroupedPageFlipDisposition::INVARIANT_FAILURE,
             .definitionIdentity = OWNER->identity,
             .route              = OWNER->activeRoute,
         };
-        result.runtimeEffects = std::move(effects);
-        return result;
     }
 
     SGroupedPageFlipResult result{
@@ -734,10 +1008,13 @@ SGroupedPageFlipResult CGroupedRuntimeAuthority::routePageFlip(uintptr_t transac
         .route              = OWNER->activeRoute,
     };
     auto       effects                     = OWNER->runtime->record(transactionId, crtcId, sequence, timestampNs);
+    const auto EFFECT_DISPOSITION          = effects.disposition;
     const bool RESERVATION_EFFECTS_APPLIED = applyReservationEffects(effects);
     result.reservationRetired              = effects.retireReservation && RESERVATION_EFFECTS_APPLIED;
+    result.successorAdopted                = effects.successorAdopted;
+    result.successorGeneration             = effects.successorGeneration;
 
-    switch (effects.disposition) {
+    switch (EFFECT_DISPOSITION) {
         case eTiledEventDisposition::RECORDED: result.disposition = eGroupedPageFlipDisposition::RECORDED; break;
         case eTiledEventDisposition::COMPLETED: result.disposition = eGroupedPageFlipDisposition::COMPLETED; break;
         case eTiledEventDisposition::QUIESCED: result.disposition = eGroupedPageFlipDisposition::QUIESCED; break;
@@ -746,9 +1023,35 @@ SGroupedPageFlipResult CGroupedRuntimeAuthority::routePageFlip(uintptr_t transac
         case eTiledEventDisposition::ALREADY_COMPLETE: result.disposition = eGroupedPageFlipDisposition::STALE; break;
         default: result.disposition = eGroupedPageFlipDisposition::INVARIANT_FAILURE; break;
     }
-    if (!RESERVATION_EFFECTS_APPLIED || !synchronizeRoute(*OWNER))
+    if (EFFECT_DISPOSITION == eTiledEventDisposition::COMPLETED) {
+        SCompletionDebt debt{
+            .transactionId       = transactionId,
+            .effects             = std::move(effects),
+            .reservationRetired  = result.reservationRetired,
+            .successorAdopted    = result.successorAdopted,
+            .successorGeneration = result.successorGeneration,
+        };
+        const auto& CURRENT_FRAMES = OWNER->runtime->currentFrames();
+        if (CURRENT_FRAMES.size() == 1) {
+            const auto* FRAMEBUFFER_OWNER = CURRENT_FRAMES.front().framebufferOwner.get();
+            const auto* BUFFER_OWNER      = CURRENT_FRAMES.front().bufferOwner.get();
+            if (FRAMEBUFFER_OWNER && BUFFER_OWNER && FRAMEBUFFER_OWNER->role() == eGroupedFrameOwnerRole::FRAMEBUFFER && BUFFER_OWNER->role() == eGroupedFrameOwnerRole::BUFFER &&
+                FRAMEBUFFER_OWNER->route() && BUFFER_OWNER->route() && sameOwner(FRAMEBUFFER_OWNER->route(), BUFFER_OWNER->route()) && FRAMEBUFFER_OWNER->publication() &&
+                sameOwner(FRAMEBUFFER_OWNER->publication(), BUFFER_OWNER->publication()) && FRAMEBUFFER_OWNER->framebuffer() && !FRAMEBUFFER_OWNER->buffer() &&
+                !BUFFER_OWNER->framebuffer() && BUFFER_OWNER->buffer() && sameOwner(FRAMEBUFFER_OWNER->route()->definitionIdentity(), OWNER->identity)) {
+                debt.acceptedRoute = FRAMEBUFFER_OWNER->route();
+                debt.publication   = FRAMEBUFFER_OWNER->publication();
+            }
+        }
+        OWNER->completionDebt.emplace(std::move(debt));
+    }
+
+    const bool ROUTE_SYNCHRONIZED = synchronizeRoute(*OWNER);
+    if (!RESERVATION_EFFECTS_APPLIED || !ROUTE_SYNCHRONIZED)
+        result.disposition = eGroupedPageFlipDisposition::INVARIANT_FAILURE;
+
+    if (EFFECT_DISPOSITION == eTiledEventDisposition::COMPLETED && consumeCompletionDebt(*OWNER, result) != eGroupedCompletionConsumeResult::DELIVERED)
         result.disposition = eGroupedPageFlipDisposition::INVARIANT_FAILURE;
-    result.runtimeEffects = std::move(effects);
     return result;
 }
 
@@ -761,6 +1064,8 @@ bool CGroupedRuntimeAuthority::terminalShutdown(eTiledRegistryShutdownProof regi
     const bool NO_CALLBACKS = registryProof == eTiledRegistryShutdownProof::BACKEND_NO_CALLBACKS && runtimeProof == eTiledRetirementProof::BACKEND_TEARDOWN_NO_CALLBACKS;
     if (!DEVICE_GONE && !NO_CALLBACKS)
         return false;
+    if (std::ranges::any_of(m_runtimes, [](const auto& entry) { return entry.second.completionDebt.has_value(); }))
+        return false;
     if (!prepareTestModesetDetach())
         return false;
 
@@ -799,7 +1104,7 @@ bool CGroupedRuntimeAuthority::busy() const noexcept {
 
 bool CGroupedRuntimeAuthority::readyForDestruction() const noexcept {
     return !m_testFramebuffer && (!m_testCleanupRegistry || m_testCleanupRegistry->pendingCount() == 0) && m_reservations.readyForDestruction() &&
-        std::ranges::all_of(m_runtimes, [](const auto& entry) { return entry.second.runtime && entry.second.runtime->readyForDestruction(); });
+        std::ranges::all_of(m_runtimes, [](const auto& entry) { return entry.second.runtime && !entry.second.completionDebt && entry.second.runtime->readyForDestruction(); });
 }
 
 size_t CGroupedRuntimeAuthority::runtimeCount() const noexcept {
diff --git a/src/backend/drm/TiledRuntimeAuthority.hpp b/src/backend/drm/TiledRuntimeAuthority.hpp
index e3efdb46c6516432497bcdc501caeb2f4e55e723..77be9f997bc536aed435f576b1616b4e6aaf2e95 100644
--- a/src/backend/drm/TiledRuntimeAuthority.hpp
+++ b/src/backend/drm/TiledRuntimeAuthority.hpp
@@ -45,9 +45,19 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthority { // NOLINT(readability-ident
     using NTiledOutputBridge::POutputDefinitionIdentity;
     using NTiledScan::PScanGroupDefinition;
 
-    // One retained frame owner for the grouped runtime. The route preserves the
-    // exact bridge/allocation/incarnation chain; future production activation
-    // must additionally provide the exact DRM FB and underlying buffer owners.
+    class CGroupedPublicationInstance;
+    class IGroupedPublicationEffectSink;
+
+    using PGroupedPublicationInstance = CSharedPointer<CGroupedPublicationInstance>;
+
+    enum class eGroupedFrameOwnerRole : uint8_t {
+        FRAMEBUFFER = 0,
+        BUFFER,
+    };
+
+    // One role-specific retained frame owner for the grouped runtime. Separate
+    // framebuffer and buffer owners let completion release the old IBuffer
+    // while retaining the old KMS FB for the runtime's last-frame lifetime.
     class AQ_TILED_RUNTIME_AUTHORITY_PRIVATE CGroupedFrameOwner final {
       public:
         CGroupedFrameOwner(const CGroupedFrameOwner&)                                       = delete;
@@ -55,14 +65,19 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthority { // NOLINT(readability-ident
         CGroupedFrameOwner&                            operator=(const CGroupedFrameOwner&) = delete;
         CGroupedFrameOwner&                            operator=(CGroupedFrameOwner&&)      = delete;
 
+        [[nodiscard]] eGroupedFrameOwnerRole             role() const noexcept;
         [[nodiscard]] const PResolvedTiledAtomicRoute& route() const noexcept;
+        [[nodiscard]] const PGroupedPublicationInstance& publication() const noexcept;
         [[nodiscard]] const CSharedPointer<CDRMFB>&    framebuffer() const noexcept;
         [[nodiscard]] const CSharedPointer<IBuffer>&   buffer() const noexcept;
 
       private:
-        CGroupedFrameOwner(PResolvedTiledAtomicRoute route, CSharedPointer<CDRMFB> framebuffer, CSharedPointer<IBuffer> buffer) noexcept;
+        CGroupedFrameOwner(eGroupedFrameOwnerRole role, PResolvedTiledAtomicRoute route, PGroupedPublicationInstance publication, CSharedPointer<CDRMFB> framebuffer,
+                           CSharedPointer<IBuffer> buffer) noexcept;
 
+        eGroupedFrameOwnerRole      m_role = eGroupedFrameOwnerRole::FRAMEBUFFER;
         PResolvedTiledAtomicRoute m_route;
+        PGroupedPublicationInstance m_publication;
         CSharedPointer<CDRMFB>    m_framebuffer;
         CSharedPointer<IBuffer>   m_buffer;
 
@@ -96,6 +111,61 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthority { // NOLINT(readability-ident
 
     using CGroupedRuntime = CTiledFrameRuntime<PGroupedFrameOwner>;
 
+    // Injected output-facing effect boundary. A future production sink will
+    // retain the exact aggregate output/primary connector and perform the
+    // scheduler -> release -> present -> frame ordering. This checkpoint has
+    // no production sink or publication callsite.
+    class AQ_TILED_RUNTIME_AUTHORITY_PRIVATE IGroupedPublicationEffectSink {
+      public:
+        virtual ~IGroupedPublicationEffectSink() = default;
+
+        virtual void frameSubmitted(uintptr_t transactionId) noexcept                             = 0;
+        virtual void frameCompleted(const PResolvedTiledAtomicRoute& acceptedRoute, const STiledPresentationSample& presentation,
+                                    std::span<const CGroupedRuntime::SRelease> releases) noexcept = 0;
+    };
+
+    enum class eGroupedCompletionConsumeResult : uint8_t {
+        DELIVERED = 0,
+        BUSY,
+        NOT_ACCEPTED,
+        STALE_TOKEN,
+        INVALID_EFFECTS,
+    };
+
+    // Stable publication/output incarnation. It carries no generation
+    // freshness; currentness is always proved by the registry + bridge gate.
+    // State changes precede injected callbacks, and m_effectActive prevents
+    // reentrant arm/rollback/accept/completion mutation.
+    class AQ_TILED_RUNTIME_AUTHORITY_PRIVATE CGroupedPublicationInstance final {
+      public:
+        CGroupedPublicationInstance(const CGroupedPublicationInstance&)                                = delete;
+        CGroupedPublicationInstance(CGroupedPublicationInstance&&)                                     = delete;
+        CGroupedPublicationInstance&                     operator=(const CGroupedPublicationInstance&) = delete;
+        CGroupedPublicationInstance&                     operator=(CGroupedPublicationInstance&&)      = delete;
+
+        [[nodiscard]] static PGroupedPublicationInstance create(const POutputDefinitionIdentity& identity, const CSharedPointer<IGroupedPublicationEffectSink>& sink) noexcept;
+        [[nodiscard]] const POutputDefinitionIdentity&   definitionIdentity() const noexcept;
+
+      private:
+        CGroupedPublicationInstance(POutputDefinitionIdentity identity, CSharedPointer<IGroupedPublicationEffectSink> sink) noexcept;
+
+        [[nodiscard]] bool                            arm(uintptr_t transactionId) noexcept;
+        [[nodiscard]] bool                            rollback(uintptr_t transactionId) noexcept;
+        [[nodiscard]] bool                            accept(uintptr_t transactionId, bool schedulerSubmit) noexcept;
+        [[nodiscard]] eGroupedCompletionConsumeResult consumeCompletion(const PGroupedPublicationInstance& completingPublication, uintptr_t transactionId,
+                                                                        const PResolvedTiledAtomicRoute& acceptedRoute, const CGroupedRuntime::SEffects& effects) noexcept;
+
+        POutputDefinitionIdentity                     m_identity;
+        CSharedPointer<IGroupedPublicationEffectSink> m_sink;
+        uintptr_t                                     m_transactionId    = 0;
+        bool                                          m_accepted         = false;
+        bool                                          m_schedulerPending = false;
+        bool                                          m_effectActive     = false;
+
+        friend class CGroupedRuntimeAuthority;
+        friend class ::Aquamarine::NDRM::NTiledRuntimeAuthorityTest::CFixtureAuthority;
+    };
+
     enum class eGroupedStageResult : uint8_t {
         STAGED = 0,
         SUCCESSOR_STAGED,
@@ -161,8 +231,43 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthority { // NOLINT(readability-ident
         eGroupedPageFlipDisposition disposition = eGroupedPageFlipDisposition::NOT_OWNED;
         POutputDefinitionIdentity   definitionIdentity;
         PResolvedTiledAtomicRoute   route;
-        CGroupedRuntime::SEffects   runtimeEffects;
+        PGroupedPublicationInstance publication;
         bool                        reservationRetired = false;
+        bool                        completionDelivered = false;
+        size_t                      releasesDelivered   = 0;
+        bool                        successorAdopted    = false;
+        uint64_t                    successorGeneration = 0;
+    };
+
+    enum class eGroupedInitialFrameStatus : uint8_t {
+        ACCEPTED = 0,
+        ACCEPTED_INVARIANT_FAILURE,
+        WRONG_THREAD,
+        BUSY,
+        TERMINAL,
+        NOT_CONFIGURED,
+        INVALID_CURRENT,
+        INVALID_PUBLICATION,
+        INVALID_FRAMEBUFFER,
+        CLEANUP_PENDING,
+        ROUTE_INVALID,
+        RUNTIME_STAGE_FAILED,
+        REQUEST_BUILD_FAILED,
+        TRANSACTION_FAILED,
+        ALLOCATION_FAILED,
+    };
+
+    struct AQ_TILED_RUNTIME_AUTHORITY_PRIVATE SGroupedInitialFrameResult {
+        eGroupedInitialFrameStatus                 status       = eGroupedInitialFrameStatus::INVALID_CURRENT;
+        NTiledAtomic::eTiledAtomicError            routeError   = NTiledAtomic::eTiledAtomicError::INVALID_INPUT;
+        NTiledAtomic::eTiledAtomicError            requestError = NTiledAtomic::eTiledAtomicError::INVALID_INPUT;
+        eGroupedStageResult                        stageResult  = eGroupedStageResult::INVALID_CURRENT;
+        NTiledAtomic::STiledFrameTransactionResult transaction;
+        STiledModeBlobCleanupOutcome               cleanup;
+        bool                                       bufferLocked          = false;
+        bool                                       submitEffectDelivered = false;
+
+        explicit                                   operator bool() const noexcept;
     };
 
     struct AQ_TILED_RUNTIME_AUTHORITY_PRIVATE SOrdinaryKMSCRTC {
@@ -265,6 +370,10 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthority { // NOLINT(readability-ident
 
         [[nodiscard]] eGroupedStageResult      stageCurrent(const POutputBridgeObservation& current, const PResolvedTiledAtomicRoute& route) noexcept;
         [[nodiscard]] SGroupedReconcileResult  reconcileCurrent(const POutputBridgeObservation& current) noexcept;
+        [[nodiscard]] SGroupedInitialFrameResult submitInitialCurrent(const POutputBridgeObservation& current, const PScanGroupDefinition& group,
+                                                                      const CSharedPointer<SOutputMode>& outputMode, const PGroupedPublicationInstance& publication,
+                                                                      const CSharedPointer<CDRMFB>& framebuffer, const CSharedPointer<IBuffer>& buffer, uintptr_t transactionId,
+                                                                      uint64_t deadlineNs) noexcept;
         [[nodiscard]] SOrdinaryKMSGateResult   gateOrdinaryKMS(std::span<const SOrdinaryKMSCRTC> crtcs, const std::function<bool()>& callback) noexcept;
         [[nodiscard]] SGroupedPageFlipResult   routePageFlip(uintptr_t transactionId, uint32_t crtcId, uint32_t sequence, uint64_t timestampNs) noexcept;
         [[nodiscard]] SGroupedQuiesceResult    quiesceAll(eTiledQuiesceReason reason) noexcept;
@@ -276,12 +385,23 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthority { // NOLINT(readability-ident
         [[nodiscard]] size_t                   runtimeCount() const noexcept;
 
       private:
+        struct SCompletionDebt {
+            uintptr_t                   transactionId = 0;
+            PResolvedTiledAtomicRoute   acceptedRoute;
+            PGroupedPublicationInstance publication;
+            CGroupedRuntime::SEffects   effects;
+            bool                        reservationRetired  = false;
+            bool                        successorAdopted    = false;
+            uint64_t                    successorGeneration = 0;
+        };
+
         struct SRuntimeRecord {
             POutputDefinitionIdentity       identity;
             NTiling::STileGroupKey          groupKey;
             PResolvedTiledAtomicRoute       activeRoute;
             PResolvedTiledAtomicRoute       successorRoute;
             CUniquePointer<CGroupedRuntime> runtime;
+            std::optional<SCompletionDebt>  completionDebt;
         };
 
         using TRuntimeMap = std::map<const void*, SRuntimeRecord>;
@@ -291,6 +411,7 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthority { // NOLINT(readability-ident
         [[nodiscard]] eGroupedStageResult      stageRecord(const POutputBridgeObservation& current, const PResolvedTiledAtomicRoute& route);
         [[nodiscard]] bool                     applyReservationEffects(const CGroupedRuntime::SEffects& effects) noexcept;
         [[nodiscard]] bool                     synchronizeRoute(SRuntimeRecord& record) noexcept;
+        [[nodiscard]] eGroupedCompletionConsumeResult consumeCompletionDebt(SRuntimeRecord& record, SGroupedPageFlipResult& result) noexcept;
         [[nodiscard]] bool                     claimsPageFlip(uintptr_t transactionId, uint32_t crtcId) const noexcept;
         [[nodiscard]] SGroupedQuiesceResult    quiesceAllUnguarded(eTiledQuiesceReason reason) noexcept;
         [[nodiscard]] SGroupedRetirementResult retireUnguarded(SRuntimeRecord& record, eTiledRetirementProof proof);
diff --git a/tests/TiledAtomic.cpp b/tests/TiledAtomic.cpp
index 82a3547fa16477084df6936a42db139aef838435..0a83eb41d2b0163deede0854c8a18a50e0650f8d 100644
--- a/tests/TiledAtomic.cpp
+++ b/tests/TiledAtomic.cpp
@@ -5,6 +5,7 @@
 #include <array>
 #include <cerrno>
 #include <cstdint>
+#include <functional>
 #include <iostream>
 #include <memory>
 #include <ranges>
@@ -101,23 +102,101 @@ using namespace Aquamarine::NDRM::NTiledOutputBridge;
 using namespace Aquamarine::NDRM::NTiledRuntimeAuthority;
 using namespace Aquamarine::NDRM::NTiledScan;
 using Hyprutils::Memory::CSharedPointer;
+using Hyprutils::Memory::CWeakPointer;
 using Hyprutils::Memory::makeShared;
 
 namespace Aquamarine::NDRM::NTiledRuntimeAuthorityTest {
+    class __attribute__((visibility("hidden"))) CRecordingPublicationSink final : public IGroupedPublicationEffectSink { // NOLINT(misc-use-internal-linkage)
+      public:
+        void frameSubmitted(uintptr_t transactionId) noexcept override {
+            ++submissions;
+            submittedToken = transactionId;
+            if (onSubmitted)
+                onSubmitted();
+        }
+
+        void frameCompleted(const PResolvedTiledAtomicRoute& acceptedRoute, const STiledPresentationSample& presentation,
+                            std::span<const CGroupedRuntime::SRelease> releases) noexcept override {
+            ++completions;
+            completionRoute = acceptedRoute;
+            completionToken = presentation.transactionId;
+            releaseCount    = releases.size();
+            releasesValid   = std::ranges::all_of(releases, [&](const auto& release) {
+                const auto* OWNER = release.owner.get();
+                return release.bufferId != 0 && OWNER && OWNER->role() == eGroupedFrameOwnerRole::BUFFER && OWNER->buffer() && OWNER->publication();
+            });
+            if (onCompleted)
+                onCompleted();
+        }
+
+        size_t                    submissions     = 0;
+        size_t                    completions     = 0;
+        size_t                    releaseCount    = 0;
+        uintptr_t                 submittedToken  = 0;
+        uintptr_t                 completionToken = 0;
+        bool                      releasesValid   = false;
+        PResolvedTiledAtomicRoute completionRoute;
+        std::function<void()>     onSubmitted;
+        std::function<void()>     onCompleted;
+    };
+
     class CFixtureAuthority final {
       public:
-        static PGroupedFrameOwner owner(const PResolvedTiledAtomicRoute& route) {
-            CSharedPointer<CGroupedFrameOwner>       mutableOwner{new CGroupedFrameOwner{route, {}, {}}};
+        template <typename T>
+        static CSharedPointer<T> opaqueResource(CWeakPointer<T>* weak = nullptr) {
+            auto carrier  = makeShared<uint64_t>(1);
+            auto resource = Hyprutils::Memory::reinterpretPointerCast<T>(carrier);
+            if (weak)
+                *weak = resource;
+            return resource;
+        }
+
+        static PGroupedFrameOwner owner(eGroupedFrameOwnerRole role, const PResolvedTiledAtomicRoute& route, const PGroupedPublicationInstance& publication,
+                                        const CSharedPointer<CDRMFB>& framebuffer, const CSharedPointer<IBuffer>& buffer) {
+            CSharedPointer<CGroupedFrameOwner>       mutableOwner{new CGroupedFrameOwner{role, route, publication, framebuffer, buffer}};
             CSharedPointer<const CGroupedFrameOwner> retained = mutableOwner;
             return PGroupedFrameOwner{std::move(retained)};
         }
 
-        static bool publishIdle(CGroupedRuntimeAuthority& authority, const POutputDefinitionIdentity& identity, uint64_t firstFramebufferId, uint64_t bufferId) {
+        static bool arm(const PGroupedPublicationInstance& publication, uintptr_t transactionId) {
+            return publication && publication->arm(transactionId);
+        }
+
+        static bool rollback(const PGroupedPublicationInstance& publication, uintptr_t transactionId) {
+            return publication && publication->rollback(transactionId);
+        }
+
+        static bool accept(const PGroupedPublicationInstance& publication, uintptr_t transactionId, bool schedulerSubmit) {
+            return publication && publication->accept(transactionId, schedulerSubmit);
+        }
+
+        static bool active(const PGroupedPublicationInstance& publication, uintptr_t transactionId) {
+            return publication && publication->m_transactionId == transactionId && publication->m_accepted;
+        }
+
+        static eGroupedCompletionConsumeResult consume(const PGroupedPublicationInstance& publication, uintptr_t transactionId, const PResolvedTiledAtomicRoute& route,
+                                                       const CGroupedRuntime::SEffects& effects) {
+            return publication ? publication->consumeCompletion(publication, transactionId, route, effects) : eGroupedCompletionConsumeResult::NOT_ACCEPTED;
+        }
+
+        static void setEffectActive(const PGroupedPublicationInstance& publication, bool active) {
+            if (publication)
+                publication->m_effectActive = active;
+        }
+
+        static bool hasCompletionDebt(CGroupedRuntimeAuthority& authority, const POutputDefinitionIdentity& identity, uintptr_t transactionId) {
+            const auto* RECORD = authority.recordFor(identity);
+            return RECORD && RECORD->completionDebt && RECORD->completionDebt->transactionId == transactionId;
+        }
+
+        static bool publishIdle(CGroupedRuntimeAuthority& authority, const POutputDefinitionIdentity& identity, const PGroupedPublicationInstance& publication,
+                                const CSharedPointer<CDRMFB>& framebuffer, const CSharedPointer<IBuffer>& buffer, uint64_t firstFramebufferId, uint64_t bufferId) {
             auto* const RECORD = authority.recordFor(identity);
-            if (!RECORD || !RECORD->runtime || !RECORD->activeRoute)
+            if (!RECORD || !RECORD->runtime || !RECORD->activeRoute || !publication || !framebuffer || !buffer)
                 return false;
 
-            const auto                                 OWNER = owner(RECORD->activeRoute);
+            const auto                                 FRAMEBUFFER_OWNER = owner(eGroupedFrameOwnerRole::FRAMEBUFFER, RECORD->activeRoute, publication, framebuffer, {});
+            const auto                                 BUFFER_OWNER      = owner(eGroupedFrameOwnerRole::BUFFER, RECORD->activeRoute, publication, {}, buffer);
             std::vector<CGroupedRuntime::SMemberFrame> frames;
             frames.reserve(RECORD->activeRoute->crtcIds().size());
             size_t index = 0;
@@ -128,8 +207,8 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthorityTest {
                         {
                             .framebufferId    = firstFramebufferId + index,
                             .bufferId         = bufferId,
-                            .framebufferOwner = OWNER,
-                            .bufferOwner      = OWNER,
+                            .framebufferOwner = FRAMEBUFFER_OWNER,
+                            .bufferOwner      = BUFFER_OWNER,
                         },
                 });
                 ++index;
@@ -137,9 +216,10 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthorityTest {
             return RECORD->runtime->publishIdle(std::move(frames));
         }
 
-        static bool accept(CGroupedRuntimeAuthority& authority, const POutputDefinitionIdentity& identity, uintptr_t transactionId, uint64_t bufferId, uint64_t deadlineNs) {
+        static bool accept(CGroupedRuntimeAuthority& authority, const POutputDefinitionIdentity& identity, const PGroupedPublicationInstance& publication,
+                           const CSharedPointer<CDRMFB>& framebuffer, const CSharedPointer<IBuffer>& buffer, uintptr_t transactionId, uint64_t bufferId, uint64_t deadlineNs) {
             auto* const RECORD = authority.recordFor(identity);
-            if (!RECORD || !RECORD->runtime || !RECORD->activeRoute)
+            if (!RECORD || !RECORD->runtime || !RECORD->activeRoute || !publication || !framebuffer || !buffer || !publication->arm(transactionId))
                 return false;
 
             STiledFlipRoute route{
@@ -147,33 +227,39 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthorityTest {
                 .generation    = RECORD->activeRoute->generation(),
                 .crtcIds       = {RECORD->activeRoute->crtcIds().begin(), RECORD->activeRoute->crtcIds().end()},
             };
-            const auto OWNER = owner(RECORD->activeRoute);
+            const auto FRAMEBUFFER_OWNER = owner(eGroupedFrameOwnerRole::FRAMEBUFFER, RECORD->activeRoute, publication, framebuffer, {});
+            const auto BUFFER_OWNER      = owner(eGroupedFrameOwnerRole::BUFFER, RECORD->activeRoute, publication, {}, buffer);
             if (RECORD->runtime->prepare(std::move(route),
                                          {
                                              .framebufferId    = RECORD->activeRoute->framebuffer().id,
                                              .bufferId         = bufferId,
-                                             .framebufferOwner = OWNER,
-                                             .bufferOwner      = OWNER,
+                                             .framebufferOwner = FRAMEBUFFER_OWNER,
+                                             .bufferOwner      = BUFFER_OWNER,
                                          },
-                                         deadlineNs) != eTiledRuntimePrepareError::NONE)
+                                         deadlineNs) != eTiledRuntimePrepareError::NONE) {
+                static_cast<void>(publication->rollback(transactionId));
                 return false;
+            }
             const auto* PREPARED = RECORD->runtime->preparedRoute();
             if (!PREPARED) {
                 static_cast<void>(RECORD->runtime->rollbackPrepared());
+                static_cast<void>(publication->rollback(transactionId));
                 return false;
             }
             const auto RESERVED = authority.m_reservations.reserveAll(*PREPARED);
             if (!RESERVED) {
                 static_cast<void>(RECORD->runtime->rollbackPrepared());
+                static_cast<void>(publication->rollback(transactionId));
                 return false;
             }
             if (!RECORD->runtime->bindReservation(RESERVED.reservation)) {
                 static_cast<void>(RECORD->runtime->rollbackPrepared());
                 static_cast<void>(authority.m_reservations.rollback(RESERVED.reservation));
+                static_cast<void>(publication->rollback(transactionId));
                 return false;
             }
             const auto ACCEPTED = RECORD->runtime->accept();
-            return ACCEPTED.accepted && authority.m_reservations.accept(RESERVED.reservation);
+            return ACCEPTED.accepted && authority.m_reservations.accept(RESERVED.reservation) && publication->accept(transactionId, ACCEPTED.schedulerSubmit);
         }
 
         static uint64_t activeGeneration(CGroupedRuntimeAuthority& authority, const POutputDefinitionIdentity& identity) {
@@ -206,6 +292,7 @@ namespace Aquamarine::NDRM::NTiledRuntimeAuthorityTest {
 }
 
 using Aquamarine::NDRM::NTiledRuntimeAuthorityTest::CFixtureAuthority;
+using Aquamarine::NDRM::NTiledRuntimeAuthorityTest::CRecordingPublicationSink;
 
 namespace {
     int  FAILURES = 0;
@@ -1300,6 +1387,52 @@ int main() {
         CHECK(authority.stageCurrent(installed, resolved.route) == eGroupedStageResult::STAGED);
         CHECK(CFixtureAuthority::nestedStage(authority, installed, resolved.route) == eGroupedStageResult::BUSY);
 
+        auto                                          rollbackSink        = makeShared<CRecordingPublicationSink>();
+        CSharedPointer<IGroupedPublicationEffectSink> rollbackSinkOwner   = rollbackSink;
+        const auto                                    rollbackPublication = CGroupedPublicationInstance::create(GROUP.definitionIdentity(), rollbackSinkOwner);
+        CHECK(!!rollbackPublication);
+        CHECK(CFixtureAuthority::arm(rollbackPublication, 4'900));
+        CHECK(CFixtureAuthority::rollback(rollbackPublication, 4'900));
+        CHECK(!CFixtureAuthority::active(rollbackPublication, 4'900));
+        CHECK(rollbackSink->submissions == 0);
+
+        auto                                          invariantSink        = makeShared<CRecordingPublicationSink>();
+        CSharedPointer<IGroupedPublicationEffectSink> invariantSinkOwner   = invariantSink;
+        const auto                                    invariantPublication = CGroupedPublicationInstance::create(GROUP.definitionIdentity(), invariantSinkOwner);
+        CHECK(!!invariantPublication);
+        CHECK(CFixtureAuthority::arm(invariantPublication, 4'901));
+        CHECK(CFixtureAuthority::accept(invariantPublication, 4'901, false));
+        CHECK(CFixtureAuthority::active(invariantPublication, 4'901));
+        CHECK(!CFixtureAuthority::rollback(invariantPublication, 4'901));
+        CHECK(!CFixtureAuthority::arm(invariantPublication, 4'902));
+        CHECK(invariantSink->submissions == 0);
+
+        auto                                          releaseSink               = makeShared<CRecordingPublicationSink>();
+        CSharedPointer<IGroupedPublicationEffectSink> releaseSinkOwner          = releaseSink;
+        const auto                                    releasePublication        = CGroupedPublicationInstance::create(GROUP.definitionIdentity(), releaseSinkOwner);
+        const auto                                    foreignReleasePublication = CGroupedPublicationInstance::create(GROUP.definitionIdentity(), releaseSinkOwner);
+        CHECK(!!releasePublication);
+        CHECK(!!foreignReleasePublication);
+        CHECK(CFixtureAuthority::arm(releasePublication, 4'903));
+        CHECK(CFixtureAuthority::accept(releasePublication, 4'903, true));
+        CGroupedRuntime::SEffects releaseEffects{
+            .disposition       = eTiledEventDisposition::COMPLETED,
+            .schedulerComplete = true,
+            .present           = true,
+            .presentation      = STiledPresentationSample{.transactionId = 4'903, .generation = resolved.route->generation()},
+        };
+        auto foreignReleaseBuffer = CFixtureAuthority::opaqueResource<IBuffer>();
+        releaseEffects.releases.push_back({
+            .bufferId = 4'903,
+            .owner    = CFixtureAuthority::owner(eGroupedFrameOwnerRole::BUFFER, resolved.route, foreignReleasePublication, {}, foreignReleaseBuffer),
+        });
+        CHECK(CFixtureAuthority::consume(releasePublication, 4'903, resolved.route, releaseEffects) == eGroupedCompletionConsumeResult::INVALID_EFFECTS);
+        CHECK(CFixtureAuthority::active(releasePublication, 4'903));
+        CHECK(releaseSink->completions == 0);
+        releaseEffects.releases.front().owner = CFixtureAuthority::owner(eGroupedFrameOwnerRole::BUFFER, resolved.route, releasePublication, {}, foreignReleaseBuffer);
+        CHECK(CFixtureAuthority::consume(releasePublication, 4'903, resolved.route, releaseEffects) == eGroupedCompletionConsumeResult::DELIVERED);
+        CHECK(releaseSink->completions == 1);
+
         std::vector<SOrdinaryKMSCRTC> ordinaryCRTCs;
         ordinaryCRTCs.reserve(resolved.route->members().size());
         for (const auto& MEMBER : resolved.route->members())
@@ -1375,14 +1508,37 @@ int main() {
         CHECK(!wrongThreadInvoked);
         CHECK(callbackCount == 1);
 
-        CHECK(CFixtureAuthority::publishIdle(authority, GROUP.definitionIdentity(), 1'500, 1'100));
+        auto                                          publicationSink      = makeShared<CRecordingPublicationSink>();
+        CSharedPointer<IGroupedPublicationEffectSink> publicationSinkOwner = publicationSink;
+        const auto                                    publication          = CGroupedPublicationInstance::create(GROUP.definitionIdentity(), publicationSinkOwner);
+        CHECK(!!publication);
+        CWeakPointer<CDRMFB>  oldFramebufferWeak;
+        CWeakPointer<IBuffer> oldBufferWeak;
+        auto                  oldFramebuffer = CFixtureAuthority::opaqueResource<CDRMFB>(&oldFramebufferWeak);
+        auto                  oldBuffer      = CFixtureAuthority::opaqueResource<IBuffer>(&oldBufferWeak);
+        CHECK(CFixtureAuthority::publishIdle(authority, GROUP.definitionIdentity(), publication, oldFramebuffer, oldBuffer, 1'500, 1'100));
+        oldFramebuffer.reset();
+        oldBuffer.reset();
         const auto LIVE_GATE = authority.gateOrdinaryKMS(ordinaryCRTCs, [&] {
             ++callbackCount;
             return true;
         });
         CHECK(LIVE_GATE.status == eOrdinaryKMSGateStatus::GROUPED_OWNERSHIP);
         CHECK(callbackCount == 1);
-        CHECK(CFixtureAuthority::accept(authority, GROUP.definitionIdentity(), 5'005, 1'101, 90'000));
+        bool submitReentry           = true;
+        bool completionReentry       = true;
+        publicationSink->onSubmitted = [&] { submitReentry = CFixtureAuthority::arm(publication, 5'006); };
+        publicationSink->onCompleted = [&] { completionReentry = CFixtureAuthority::arm(publication, 5'007); };
+        CWeakPointer<CDRMFB>  newFramebufferWeak;
+        CWeakPointer<IBuffer> newBufferWeak;
+        auto                  newFramebuffer = CFixtureAuthority::opaqueResource<CDRMFB>(&newFramebufferWeak);
+        auto                  newBuffer      = CFixtureAuthority::opaqueResource<IBuffer>(&newBufferWeak);
+        CHECK(CFixtureAuthority::accept(authority, GROUP.definitionIdentity(), publication, newFramebuffer, newBuffer, 5'005, 1'101, 90'000));
+        newFramebuffer.reset();
+        newBuffer.reset();
+        CHECK(!submitReentry);
+        CHECK(publicationSink->submissions == 1);
+        CHECK(publicationSink->submittedToken == 5'005);
 
         CHECK(bridge.clear());
         CHECK(!bridge.diagnosticInstalled());
@@ -1419,28 +1575,56 @@ int main() {
         const auto first = authority.routePageFlip(5'005, resolved.route->crtcIds().front(), 30, 200);
         CHECK(first.claimed);
         CHECK(first.disposition == eGroupedPageFlipDisposition::RECORDED);
-        CHECK(first.runtimeEffects.releases.empty());
+        CHECK(!first.completionDelivered);
+        CHECK(first.releasesDelivered == 0);
 
-        auto completion = authority.routePageFlip(5'005, resolved.route->crtcIds().back(), 40, 220);
+        CFixtureAuthority::setEffectActive(publication, true);
+        const auto completion = authority.routePageFlip(5'005, resolved.route->crtcIds().back(), 40, 220);
         CHECK(completion.claimed);
-        CHECK(completion.disposition == eGroupedPageFlipDisposition::COMPLETED);
+        CHECK(completion.disposition == eGroupedPageFlipDisposition::INVARIANT_FAILURE);
         CHECK(completion.reservationRetired);
-        CHECK(completion.runtimeEffects.schedulerComplete);
-        CHECK(completion.runtimeEffects.present);
-        CHECK(completion.runtimeEffects.successorAdopted);
-        CHECK(completion.runtimeEffects.successorGeneration == successorResolved.route->generation());
-        CHECK(completion.runtimeEffects.releases.size() == 1);
-        CHECK(completion.runtimeEffects.releases.front().bufferId == 1'100);
-        CHECK(completion.runtimeEffects.releases.front().owner.get());
-        CHECK(sameOwner(completion.runtimeEffects.releases.front().owner.get()->route(), resolved.route));
+        CHECK(!completion.completionDelivered);
+        CHECK(completion.releasesDelivered == 0);
+        CHECK(completion.successorAdopted);
+        CHECK(completion.successorGeneration == successorResolved.route->generation());
         CHECK(sameOwner(completion.route, resolved.route));
+        CHECK(sameOwner(completion.publication, publication));
+        CHECK(publicationSink->completions == 0);
+        CHECK(CFixtureAuthority::hasCompletionDebt(authority, GROUP.definitionIdentity(), 5'005));
+        CHECK(!oldBufferWeak.expired());
+        CHECK(!authority.terminalShutdown(eTiledRegistryShutdownProof::BACKEND_NO_CALLBACKS, eTiledRetirementProof::BACKEND_TEARDOWN_NO_CALLBACKS));
+
+        CFixtureAuthority::setEffectActive(publication, false);
+        const auto completionRetry = authority.routePageFlip(5'005, resolved.route->crtcIds().back(), 41, 221);
+        CHECK(completionRetry.claimed);
+        CHECK(completionRetry.disposition == eGroupedPageFlipDisposition::COMPLETED);
+        CHECK(completionRetry.reservationRetired);
+        CHECK(completionRetry.completionDelivered);
+        CHECK(completionRetry.releasesDelivered == 1);
+        CHECK(completionRetry.successorAdopted);
+        CHECK(completionRetry.successorGeneration == successorResolved.route->generation());
+        CHECK(sameOwner(completionRetry.route, resolved.route));
+        CHECK(sameOwner(completionRetry.publication, publication));
+        CHECK(!CFixtureAuthority::hasCompletionDebt(authority, GROUP.definitionIdentity(), 5'005));
+        CHECK(publicationSink->completions == 1);
+        CHECK(publicationSink->completionToken == 5'005);
+        CHECK(publicationSink->releaseCount == 1);
+        CHECK(publicationSink->releasesValid);
+        CHECK(sameOwner(publicationSink->completionRoute, resolved.route));
+        CHECK(!completionReentry);
+        CHECK(oldBufferWeak.expired());
+        CHECK(!oldFramebufferWeak.expired());
+        CHECK(!newFramebufferWeak.expired());
+        CHECK(!newBufferWeak.expired());
+        CHECK(CFixtureAuthority::arm(publication, 5'008));
+        CHECK(CFixtureAuthority::rollback(publication, 5'008));
         CHECK(CFixtureAuthority::activeGeneration(authority, GROUP.definitionIdentity()) == successorResolved.route->generation());
 
-        const auto stale = authority.routePageFlip(5'005, resolved.route->crtcIds().back(), 41, 221);
+        const auto stale = authority.routePageFlip(5'005, resolved.route->crtcIds().back(), 42, 222);
         CHECK(stale.claimed);
         CHECK(stale.disposition == eGroupedPageFlipDisposition::STALE);
+        CHECK(publicationSink->completions == 1);
 
-        completion.runtimeEffects.releases.clear();
         const auto QUIESCED = authority.quiesceAll(eTiledQuiesceReason::BACKEND_TEARDOWN);
         CHECK(!QUIESCED.invariantFailed);
         CHECK(QUIESCED.quiesced == 1);
@@ -1461,6 +1645,9 @@ int main() {
         CHECK(!ORDINARY_AFTER_TERMINAL.claimed);
         CHECK(ORDINARY_AFTER_TERMINAL.disposition == eGroupedPageFlipDisposition::TERMINAL);
         CHECK(authority.readyForDestruction());
+        CHECK(oldFramebufferWeak.expired());
+        CHECK(newFramebufferWeak.expired());
+        CHECK(newBufferWeak.expired());
     }
 
     return FAILURES == 0 ? 0 : 1;
diff --git a/tests/TiledDRMIntegration.cpp b/tests/TiledDRMIntegration.cpp
index cdc6682eedd06f09ea75846e7d517bd4867d1d38..15f68cf20dcd5dd4c203ce86f16fc4acd0be2f54 100644
--- a/tests/TiledDRMIntegration.cpp
+++ b/tests/TiledDRMIntegration.cpp
@@ -98,6 +98,13 @@ namespace Aquamarine::NDRM::NTiledDRMIntegrationTest {
             return registry.executeCurrentTestModeset(lifetime, expected, group, outputMode);
         }
 
+        static SGroupedInitialFrameResult submitInitialFrame(CTiledDRMIntegrationRegistry& registry, const PBackendLifetime& lifetime, const POutputBridgeObservation& expected,
+                                                             const PScanGroupDefinition& group, const CSharedPointer<Aquamarine::SOutputMode>& outputMode,
+                                                             const PGroupedPublicationInstance& publication, const CSharedPointer<Aquamarine::CDRMFB>& framebuffer,
+                                                             const CSharedPointer<Aquamarine::IBuffer>& buffer, uintptr_t transactionId, uint64_t deadlineNs) {
+            return registry.submitCurrentTestInitialFrame(lifetime, expected, group, outputMode, publication, framebuffer, buffer, transactionId, deadlineNs);
+        }
+
         static bool exhaustResourceEpoch(CTiledDRMIntegrationRegistry& registry, const PBackendLifetime& lifetime) {
             return registry.exhaustTestResourceEpoch(lifetime);
         }
@@ -107,6 +114,18 @@ namespace Aquamarine::NDRM::NTiledDRMIntegrationTest {
 using Aquamarine::NDRM::NTiledDRMIntegrationTest::CFixtureAuthority;
 
 namespace {
+    class __attribute__((visibility("hidden"))) CNoopPublicationSink final : public IGroupedPublicationEffectSink {
+      public:
+        void frameSubmitted(uintptr_t) noexcept override {}
+        void frameCompleted(const PResolvedTiledAtomicRoute&, const Aquamarine::NDRM::STiledPresentationSample&, std::span<const CGroupedRuntime::SRelease>) noexcept override {}
+    };
+
+    template <typename T>
+    CSharedPointer<T> opaqueResource() {
+        auto carrier = makeShared<uint64_t>(1);
+        return reinterpretPointerCast<T>(carrier);
+    }
+
     int value(eScanBeginResult result) {
         return static_cast<int>(result);
     }
@@ -598,6 +617,14 @@ int main() {
             CFixtureAuthority::executeTestModeset(registry, LIFETIME, BRIDGE, ALLOCATED_GROUP ? ALLOCATED_GROUP->scanDefinition() : PScanGroupDefinition{}, OUTPUT_MODE);
         EXPECT(value(STALE_TEST_MODESET.status), value(eGroupedTestModesetStatus::INVALID_CURRENT));
         EXPECT(atomicOperations->submits, 1U);
+        auto                                          staleSink        = makeShared<CNoopPublicationSink>();
+        CSharedPointer<IGroupedPublicationEffectSink> staleSinkOwner   = staleSink;
+        const auto                                    stalePublication = CGroupedPublicationInstance::create(DEFINITION_IDENTITY, staleSinkOwner);
+        const auto                                    STALE_INITIAL =
+            CFixtureAuthority::submitInitialFrame(registry, LIFETIME, BRIDGE, ALLOCATED_GROUP ? ALLOCATED_GROUP->scanDefinition() : PScanGroupDefinition{}, OUTPUT_MODE,
+                                                  stalePublication, opaqueResource<Aquamarine::CDRMFB>(), opaqueResource<Aquamarine::IBuffer>(), 8'001, 100'000);
+        EXPECT(STALE_INITIAL.status == eGroupedInitialFrameStatus::INVALID_CURRENT, true);
+        EXPECT(atomicOperations->submits, 1U);
         EXPECT(CFixtureAuthority::withCurrent(registry, LIFETIME, SHADOW, [&](const CPlan&, const SCurrentState&) { ++callbacks; }), false);
         EXPECT(CFixtureAuthority::withCurrentOutputBridge(registry, LIFETIME, SHADOW, [&](const auto&) { ++callbacks; }), false);
         EXPECT(callbacks, 1U);
diff --git a/tests/TiledRuntime.cpp b/tests/TiledRuntime.cpp
index 8e437be3584ce598047ce814607586ac3d95264c..5288750baf383354a145dbeb30f4680434589a33 100644
--- a/tests/TiledRuntime.cpp
+++ b/tests/TiledRuntime.cpp
@@ -388,10 +388,11 @@ int main() {
         EXPECT(leftWeak.expired(), false);
         EXPECT(rightWeak.expired(), false);
         EXPECT(bufferWeak.expired(), false);
+        EXPECT(std::ranges::all_of(runtime.lastFrames(), [](const auto& last) { return !last.bufferOwner; }), true);
         completed.releases.clear();
         EXPECT(leftWeak.expired(), false);
         EXPECT(rightWeak.expired(), false);
-        EXPECT(bufferWeak.expired(), false);
+        EXPECT(bufferWeak.expired(), true);
         EXPECT(registry.retire(completed.reservation.value_or(STiledFlipReservation{})), true);
 
         EXPECT(runtime.quiesce(eTiledQuiesceReason::OUTPUT_DISABLED).requestRecovery, true);