feat(memory): architect contradiction-check (B§4, display-only)
- PossibleContradictionFlaggedEvent + RelatedDecision (registered + serialization test) - ArchitectContradictionChecker: L3 similarity retrieval over prior decisions, threshold-gated, fake-testable; non-blocking (surfaces candidates only) - live wiring left as documented TODO (needs an architect-decision emit hook + in-session decision embedding into L3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package com.correx.core.events.events
|
||||
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.core.events.types.StageId
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* One prior decision/ADR surfaced as semantically near a new architect decision.
|
||||
* [source] is the L3 entry's turnId (or a decision id) the line came from; [score] is the
|
||||
* similarity of the prior decision to the new one.
|
||||
*/
|
||||
@Serializable
|
||||
data class RelatedDecision(
|
||||
val summary: String,
|
||||
val score: Double,
|
||||
val source: String,
|
||||
)
|
||||
|
||||
/**
|
||||
* Display-only architect contradiction surfacing (BACKLOG §B-§4). Lists prior decisions
|
||||
* semantically near the new one so the operator can spot a reversal. Non-blocking: this event
|
||||
* only surfaces similarity candidates for an operator to eyeball — it never halts or fails a
|
||||
* stage, and there is no LLM judge.
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("PossibleContradictionFlagged")
|
||||
data class PossibleContradictionFlaggedEvent(
|
||||
val sessionId: SessionId,
|
||||
val stageId: StageId,
|
||||
val decisionSummary: String,
|
||||
val related: List<RelatedDecision>,
|
||||
) : EventPayload
|
||||
@@ -20,6 +20,7 @@ import com.correx.core.events.events.OperatorProfileBoundEvent
|
||||
import com.correx.core.events.events.ProjectProfileBoundEvent
|
||||
import com.correx.core.events.events.SessionWorkspaceBoundEvent
|
||||
import com.correx.core.events.events.ContextTruncatedEvent
|
||||
import com.correx.core.events.events.PossibleContradictionFlaggedEvent
|
||||
import com.correx.core.events.events.EventPayload
|
||||
import com.correx.core.events.events.ExecutionPlanLockedEvent
|
||||
import com.correx.core.events.events.ExecutionPlanRejectedEvent
|
||||
@@ -135,6 +136,7 @@ val eventModule = SerializersModule {
|
||||
subclass(CritiqueOutcomeCorrelatedEvent::class)
|
||||
subclass(StageCheckpointPassedEvent::class)
|
||||
subclass(StageCheckpointFailedEvent::class)
|
||||
subclass(PossibleContradictionFlaggedEvent::class)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.correx.core.events.serialization
|
||||
|
||||
import com.correx.core.events.events.EventPayload
|
||||
import com.correx.core.events.events.PossibleContradictionFlaggedEvent
|
||||
import com.correx.core.events.events.RelatedDecision
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.core.events.types.StageId
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ContradictionEventSerializationTest {
|
||||
|
||||
@Test
|
||||
fun `PossibleContradictionFlaggedEvent round-trips as polymorphic EventPayload`() {
|
||||
val sample: EventPayload = PossibleContradictionFlaggedEvent(
|
||||
sessionId = SessionId("s"),
|
||||
stageId = StageId("architect"),
|
||||
decisionSummary = "Use Postgres for the event store.",
|
||||
related = listOf(
|
||||
RelatedDecision(
|
||||
summary = "Decided to use SQLite for the event store.",
|
||||
score = 0.91,
|
||||
source = "project:/repo",
|
||||
),
|
||||
),
|
||||
)
|
||||
val encoded = eventJson.encodeToString(EventPayload.serializer(), sample)
|
||||
assertTrue(
|
||||
encoded.contains("\"type\":\"PossibleContradictionFlagged\""),
|
||||
"SerialName must be present: $encoded",
|
||||
)
|
||||
val decoded = eventJson.decodeFromString(EventPayload.serializer(), encoded)
|
||||
assertEquals(sample, decoded)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user