Skip to content

Proposition lifecycle events #8

@jimador

Description

@jimador

Observation

When propositions change state (created, revised, superseded, contradicted), there's no event-driven notification. Consumers that need to react — cache invalidation, audit logging, metrics, cascading updates — must poll the repository or wrap every service method with callbacks.

PropositionReviser returns RevisionResult (New/Merged/Reinforced/Contradicted/Generalized), but this is a return value from a synchronous call. Independent components can't observe revision outcomes without being directly coupled to the caller.

What DICE already has

  • RevisionResult sealed hierarchy — captures what happened, but only as a return value
  • PropositionStatus — ACTIVE, SUPERSEDED, CONTRADICTED, PROMOTED — status changes are implicit in repository updates
  • PropositionPipeline — orchestrates extract → revise → persist, but no event hooks
  • Spring Framework — DICE already uses Spring; ApplicationEventPublisher + @EventListener is the idiomatic pattern

Proposal

A sealed event hierarchy published via Spring's ApplicationEventPublisher:

sealed class PropositionLifecycleEvent(
    val contextId: ContextId,
    val propositionId: String,
    val timestamp: Instant = Instant.now()
) {
    class Created(contextId, propositionId, val proposition: Proposition)
    class Revised(contextId, propositionId, val revisionResult: RevisionResult)
    class StatusChanged(contextId, propositionId,
                        val oldStatus: PropositionStatus, val newStatus: PropositionStatus)
    class Deleted(contextId, propositionId)
}

PropositionPipeline and PropositionReviser implementations publish events after state-changing operations. The publisher is optional (ApplicationEventPublisher? = null) for backward compatibility.

Consumers listen via standard Spring:

@EventListener
fun onCreated(event: PropositionLifecycleEvent.Created) {
    metricsRegistry.counter("dice.propositions.created").increment()
}

Use cases

  • Cache invalidation on state change
  • OTEL metrics/spans on lifecycle transitions
  • Audit trail with timestamps and reasons
  • Cascading updates (superseded proposition → update dependent abstractions)
  • Real-time UI updates

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions