diff --git a/apps/server/src/main/kotlin/com/correx/apps/server/bridge/DomainEventMapper.kt b/apps/server/src/main/kotlin/com/correx/apps/server/bridge/DomainEventMapper.kt index f0e81ca0..4aaf83cf 100644 --- a/apps/server/src/main/kotlin/com/correx/apps/server/bridge/DomainEventMapper.kt +++ b/apps/server/src/main/kotlin/com/correx/apps/server/bridge/DomainEventMapper.kt @@ -21,6 +21,9 @@ import com.correx.core.events.events.TransitionExecutedEvent import com.correx.core.events.events.WorkflowCompletedEvent import com.correx.core.events.events.WorkflowFailedEvent import com.correx.core.events.types.ArtifactId +import org.slf4j.LoggerFactory + +private val log = LoggerFactory.getLogger("DomainEventMapper") class DomainEventMapper(private val artifactStore: ArtifactStore = NoopArtifactStore) { suspend fun map(event: StoredEvent): ServerMessage? = @@ -138,7 +141,15 @@ suspend fun domainEventToServerMessage( ) is ApprovalRequestedEvent -> mapApprovalRequested(p, seq, sessionSequence) - else -> null + else -> { + log.debug( + "DomainEventMapper: unmapped payload type={} sessionId={} sequence={}", + p::class.simpleName, + event.metadata.sessionId, + event.sequence, + ) + null + } } } diff --git a/apps/server/src/test/kotlin/com/correx/apps/server/bridge/DomainEventMapperTest.kt b/apps/server/src/test/kotlin/com/correx/apps/server/bridge/DomainEventMapperTest.kt index 3a48976d..13d1945c 100644 --- a/apps/server/src/test/kotlin/com/correx/apps/server/bridge/DomainEventMapperTest.kt +++ b/apps/server/src/test/kotlin/com/correx/apps/server/bridge/DomainEventMapperTest.kt @@ -37,8 +37,15 @@ import com.correx.core.events.types.ValidationReportId import com.correx.core.inference.TokenUsage import kotlinx.coroutines.test.runTest import kotlinx.datetime.Instant +import org.apache.logging.log4j.Level +import org.apache.logging.log4j.LogManager +import org.apache.logging.log4j.core.LogEvent +import org.apache.logging.log4j.core.LoggerContext +import org.apache.logging.log4j.core.appender.AbstractAppender +import org.apache.logging.log4j.core.config.Property import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class DomainEventMapperTest { @@ -368,4 +375,33 @@ class DomainEventMapperTest { val result = domainEventToServerMessage(event, noopStore, sessionSequence = 0L) assertNull(result) } + + private class TestAppender : AbstractAppender("TestCapture", null, null, true, Property.EMPTY_ARRAY) { + val events = mutableListOf() + override fun append(event: LogEvent) { + events.add(event.toImmutable()) + } + } + + @Test + fun `unmapped event emits debug log`(): Unit = runTest { + val ctx = LogManager.getContext(false) as LoggerContext + val logger = ctx.getLogger("DomainEventMapper") + val appender = TestAppender().also { it.start() } + logger.addAppender(appender) + val origLevel = logger.level + logger.level = Level.DEBUG + try { + val event = storedEvent(SessionStartedEvent(sessionId = sessionId)) + val result = domainEventToServerMessage(event, noopStore, sessionSequence = 0L) + assertNull(result) + assertEquals(1, appender.events.size) + assertEquals(Level.DEBUG, appender.events[0].level) + assertTrue(appender.events[0].message.formattedMessage.contains("SessionStartedEvent")) + } finally { + logger.removeAppender(appender) + appender.stop() + logger.level = origLevel + } + } }