feat(personalization): OperatorProfileBoundEvent + bind-at-start + inject about context
Records operator profile as a snapshot event at session start (invariants #8/#9), populates SessionState.boundProfile via reducer, and injects the about text as a pinned L0 SYSTEM context entry in every stage. Gated by PersonalizationConfig.enabled.
This commit is contained in:
@@ -11,6 +11,8 @@ import com.correx.core.artifacts.kind.JsonSchema
|
||||
import com.correx.core.artifactstore.ArtifactStore
|
||||
import com.correx.core.config.ConfigLoader
|
||||
import com.correx.core.config.CorrexConfig
|
||||
import com.correx.core.config.OperatorProfile
|
||||
import com.correx.core.config.ProfileLoader
|
||||
import com.correx.core.config.ProviderConfig
|
||||
import com.correx.core.context.builder.DefaultContextPackBuilder
|
||||
import com.correx.core.context.compression.DefaultContextCompressor
|
||||
@@ -94,6 +96,9 @@ fun main() {
|
||||
logStoresInfo(eventStore, artifactStore)
|
||||
|
||||
val correxConfig = ConfigLoader.load()
|
||||
val operatorProfile: OperatorProfile? = if (correxConfig.personalization.enabled) {
|
||||
ProfileLoader.load()
|
||||
} else null
|
||||
val eventDispatcher = EventDispatcher(eventStore)
|
||||
|
||||
// Managed path: [[models]] present → correx spawns llama-server at boot
|
||||
@@ -342,6 +347,7 @@ fun main() {
|
||||
narrationMaxPerRun = routerConfig.narration.maxPerRun,
|
||||
projectMemory = projectMemory,
|
||||
freestyleDriver = freestyleDriver,
|
||||
operatorProfile = operatorProfile,
|
||||
)
|
||||
module.start()
|
||||
log.info("==============================")
|
||||
|
||||
@@ -10,9 +10,11 @@ import com.correx.core.approvals.ApprovalProjector
|
||||
import com.correx.core.approvals.DefaultApprovalReducer
|
||||
import com.correx.core.approvals.DefaultApprovalRepository
|
||||
import com.correx.core.artifactstore.ArtifactStore
|
||||
import com.correx.core.config.OperatorProfile
|
||||
import com.correx.core.events.events.ApprovalRequestedEvent
|
||||
import com.correx.core.events.events.EventMetadata
|
||||
import com.correx.core.events.events.NewEvent
|
||||
import com.correx.core.events.events.OperatorProfileBoundEvent
|
||||
import com.correx.core.events.events.OrchestrationResumedEvent
|
||||
import com.correx.core.events.events.WorkflowFailedEvent
|
||||
import com.correx.core.events.stores.EventStore
|
||||
@@ -75,6 +77,8 @@ class ServerModule(
|
||||
// Driver for the two-phase freestyle workflow: locks the plan and runs phase 2.
|
||||
// Null on non-freestyle paths; injected by Main when freestyle is configured.
|
||||
private val freestyleDriver: FreestyleDriver? = null,
|
||||
// Operator profile snapshot loaded at server start. Null when personalization is disabled.
|
||||
private val operatorProfile: OperatorProfile? = null,
|
||||
) {
|
||||
val approvalCoordinator: ApprovalCoordinator = approvalCoordinator ?: ApprovalCoordinator(
|
||||
orchestrator = orchestrator,
|
||||
@@ -143,6 +147,29 @@ class ServerModule(
|
||||
pm.retrieveAndSeed(sessionId, pm.repoRoot())
|
||||
}
|
||||
}
|
||||
// Bind operator profile snapshot as an event so replay reads the recorded
|
||||
// fact rather than re-reading the live file (invariants #8/#9).
|
||||
operatorProfile?.let { profile ->
|
||||
eventStore.append(
|
||||
NewEvent(
|
||||
metadata = EventMetadata(
|
||||
eventId = EventId(java.util.UUID.randomUUID().toString()),
|
||||
sessionId = sessionId,
|
||||
timestamp = Clock.System.now(),
|
||||
schemaVersion = 1,
|
||||
causationId = null,
|
||||
correlationId = null,
|
||||
),
|
||||
payload = OperatorProfileBoundEvent(
|
||||
sessionId = sessionId,
|
||||
about = profile.about,
|
||||
approvalMode = profile.preferences.approvalMode,
|
||||
preferredModels = profile.preferences.preferredModels,
|
||||
conventions = profile.preferences.conventions,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
runCatching {
|
||||
orchestrator.run(sessionId, graph, sessionConfig)
|
||||
// After a successful freestyle planning run, lock the plan and execute phase 2.
|
||||
|
||||
Reference in New Issue
Block a user