feat(router): rubber-duck idea capture + feed

The rubber-duck path emits a fenced {"ideas":[…]} block; Ideas.parse strips it
from the chat turn and onUserInput records an IdeaCapturedEvent each (CHAT only).
IdeaReader folds eventStore.allEvents() into the active cross-session board, and
DefaultRouterContextBuilder injects a capped "## Ideas" entry — router-only, so
workflow stages never see it. Extended SYSTEM_PROMPT option (d) to capture ideas.
This commit is contained in:
2026-06-14 14:25:49 +04:00
parent 3ac0a140ec
commit 400ae5729a
8 changed files with 258 additions and 5 deletions
@@ -24,6 +24,7 @@ import com.correx.core.inference.NoopEmbedder
import com.correx.core.inference.Tokenizer
import com.correx.core.router.DefaultRouterContextBuilder
import com.correx.core.router.DefaultRouterFacade
import com.correx.core.router.IdeaReader
import com.correx.core.router.DefaultRouterReducer
import com.correx.core.router.DefaultRouterRepository
import com.correx.core.router.RouterFacade
@@ -300,7 +301,8 @@ object InfrastructureModule {
val projector = RouterProjector(reducer)
val replayer = DefaultEventReplayer(eventStore, projector)
val repository = DefaultRouterRepository(replayer)
val contextBuilder = DefaultRouterContextBuilder(config, tokenizer)
val ideaReader = IdeaReader(eventStore)
val contextBuilder = DefaultRouterContextBuilder(config, tokenizer, ideaProvider = { ideaReader.activeIdeas() })
return DefaultRouterFacade(repository, contextBuilder, inferenceRouter, eventStore, config, null, embedder, l3MemoryStore, workflowSummaryProvider, sessionProfileProvider)
}
}