Development notes from across the CaseHub ecosystem.
Issue #31 proposed putting ganglion internal state on a case blackboard — Drools CEP sessions, Bayesian posteriors, anything a stateful ganglion accumulates over time. The original RAS spec had this as an optional pat...
The branch that nobody owned
The Type That Replaced Object
Showing the Work in Similarity
Five small issues had been sitting in the backlog since the structured fields (#89) and sequence similarity (#92) work landed. Each was a gap noticed during implementation and deferred — not because it was hard, but b...
CBR cases in neocortex have been point-in-time snapshots since day one — flat features like race, MMR, and game phase. The structured fields work (#89) added nested objects and lists for richer case anatomy, but those...
CaseHub Neocortex — When Flat Features Aren’t Enough
CaseHub RAS — The Store That Learned to Fail
Part of a series on #124 — Consolidate RrfFusion with generic CbrFusion. Previous: Three Implementations of the Same Algorithm.
Three Implementations of the Same Algorithm
The Score That Lied
The desired-state runtime started with an implicit assumption: one domain per deployment. A single ActualStateAdapter, a single EventSource, a single NodeProvisioner. That was fine for teaching examples and single-pur...
The Workbench Problem
The approval-gate component had a quiet blind spot. It sent a PUT to complete a gate decision, checked response.ok, and threw the response body away. The gate.decided event carried only what the client already knew — ...
The reranking issue asked for the decorator to live in rag/ alongside HybridCaseRetriever. That felt wrong before I could articulate why — a gut reaction to the dependency graph. rag/ depends on inference-api and infe...
Every design-review workspace already has a version history. Each implementor round produces a git commit, and the tracker records **Spec commit:** → abc123 per issue. The timeline was sitting in the data — it just wa...
A platform convention isn’t real until the second project adopts it. The first adopter shaped it; the second one proves it generalises.
The original design was straightforward — attach a LocalSimilarityFunction to each FeatureField and let the scorer call it. LocalSimilarityFunction is a @FunctionalInterface, already used for per-field overrides via t...
The issue said “replace code-review.” I disagreed with my own issue.
CaseHub — Trust Closes the Loop
Part of a series on the data-table build. Previous: The Platform Table.
Arc’s @Decorator support has a gap nobody warns you about. If the bean being decorated was created by a @Produces method, the decorator registers at build time, passes every diagnostic check, and then silently does no...
Every CaseHub app needs tables. Until today, every CaseHub app that needed a table would have had to build its own — or use the one baked into pages-viz, which is coupled to the pages-runtime data pipeline and has no ...
I filed a bug that was already fixed. That’s the short version.
When desired state learns to finish
The queue board redesign left blocks-ui with a solid inbox and detail panel, but no shared primitives for the things every CaseHub app actually needs: deadline indicators, metric dashboards, and approval gates. Four i...
Three Bugs Where There Was One
Part of a series on #7 — DroolsSessionStore: persistent implementation for restart survival.
The SNAPSHOT That Wasn’t There
Added JSON Schema validation to the worker executor — but with an asymmetry that took some design thought: input validation rejects (returning a Failed result before the function ever runs), while output validation on...
The Document That Nobody Read
Nine Issues, One Branch, and a Chicken-and-Egg Problem
The batch that closed six issues taught me something I should have seen earlier: neocortex’s CBR retrieval was architecturally wrong.
Part of a series on #172 — CloudEvent WorkItem Bridge. Previous: Six Issues, One Branch.
The CBR dual-store architecture has a blind spot I hadn’t noticed until reconciliation forced the question. QdrantCbrCaseMemoryStore delegates durable storage to CaseMemoryStore — JPA or SQLite — and maintains a Qdran...
The last session landed the universal routing strategy convention (#634) — NamedStrategy, StrategyResolver, five SPIs retrofitted. That work left a trail of follow-on issues: evaluation happening in the wrong place, n...
The sixth worker module — workers-k8s — shipped two days ago. A K8s Job can run for hours. The in-memory completion registry doesn’t survive a process restart. That’s a qualitatively different problem from HTTP worker...
The CBR store has been embedding problem() text at write time since it was built. Every case goes in with a dense vector alongside its payload filters. But retrieval never used it — scrollAsync with payload filters, s...
The backlog had one item in it. That’s not because there’s one thing to do — it’s because nobody had looked at what was open. Ten issues in GitHub, and the handover said “pick up #152.”
The Qhorus normative layer has had a clear speech act taxonomy for months — nine types, seven commitment states, a sealed CommitmentStore. casehub-work has had a complete WorkItem lifecycle for nearly as long — twelve...
The Tag That Didn’t Match
The Remote That Pointed Somewhere Else
Seven issues, all small, all on one branch. The kind of session where the value isn’t in any single change but in the cumulative surface area they open for downstream consumers.
The Great Memory Migration
The question behind #279 was whether WorkItemGroupLifecycleEvent should integrate into the WorkItemEvent hierarchy — share a common base, implement the interface, or remain standalone. It was filed during the #278 API...
Closing the Result Model
I started this branch thinking issue #13 was about making provisioners return PendingApproval. The issue body described a “HumanNodeProvisioner” that returns PendingApproval with a plan artifact, gets called back afte...
The Rename That Touched Everything
Three features on one branch again. Discord needed two fixes — message history wasn’t downloading attachments, and the inbound translator was silently dropping them. The MCP tool needed the rest of the embed surface e...
One Model, Three Signals
I started this session thinking I was adding a similarity search API. I finished it questioning whether the repo should be renamed.
The guided walkthrough pages for casehub-clinical looked complete — shipped under #105 with all 8 steps and 6 explore pages. Issue #98 asked for specific things: a target-vs-actual enrollment bar chart, an endorsement...
Three Legs and a Flat Namespace
I came into this branch with a clear problem: two JVMs processing events for the same situation both evaluate to CREATE_CASE, both fire caseTrigger.fire(), and you get a duplicate case. The #18 work had already put OC...
The Hortora engine benchmark proved what I suspected — nomic-embed-text treats @DefaultBean and ConcurrentHashMap as generic English tokens. Dense vector search returns WireMock entries when you search for CDI annotat...
Part of a series on #11 — runtime enhancements. Previous: The deferrals that took an afternoon.
The issue for #31 described a tiered search pipeline: store both full-precision and truncated+binary-quantized vectors per point, use the compact one for fast first-pass retrieval, rescore against the full-precision o...
The Hortora engine’s garden corpus hit ~6,500 entries. When CorpusIngestionService bootstraps from an empty cursor, it passes every chunk to QdrantEmbeddingIngestor.ingest() in a single call. Three unbounded operation...
Part of a series on #3 — JavaSwitchGanglion. Previous: The Deferrals That Took an Afternoon.
The rag-hyde module had the wrong name from the start. It was always a generic query expansion decorator — it called QueryExpander.expand() and delegated. It didn’t know or care about HyDE. But HyDE was the first stra...
CaseHub RAS — The Runtime That Found Its Own Clock
Three issues sat in the casehub-ras backlog since Epic 2 closed: a YAML provider for situation definitions (#13), ANTI signal handling in the trigger policy (#15), and compact() invocation for persistent situations (#...
The native image gate passed weeks ago. C2 proved both JNI layers — ONNX Runtime and HuggingFace Tokenizers — work in Quarkus native image on macOS ARM. Reachability metadata shipped in inference-quarkus. The gate was...
I’d been staring at CaseRetriever.retrieve(String query, ...) for weeks without seeing the problem. The String query parameter was doing three separate things: providing text for dense embedding, providing text for sp...
CaseHub RAS — The Collection Strategy That Started With the Wrong Ordering
CaseHub Worker — First Blood
Part of a series on #4 — DroolsGanglion. Previous: The API That Didn’t Wrap Anything.
The spec for reactive CRAG looked straightforward: mirror the blocking CorrectiveCaseRetriever as a @Decorator on ReactiveCaseRetriever, swap fire() for fireAsync(), wrap the evaluator call in runSubscriptionOn(). Two...
The RAS design spec was written on June 12. Two days later, the parent repo’s layering decisions landed — and they made a quiet but significant choice: io.cloudevents.CloudEvent is the platform’s typed CDI event envel...
CaseHub Neural-Text — Fifteen Branches and Nine Missing Posts
CaseHub Neural-Text — The Guard That Isn’t a Guard
The trailing edges, trailed
Trailing Edges
Showing the Work
Four Reviews and a Fake Class
Fifty-Six Files and a Hash Bug
The Storage Layer That Wasn’t There
When Your Bridge Is the Problem It Solves
Where the Protocol Said One Thing and the Codebase Said Another
The RAG Pipeline That Dropped Its Framework
CaseHub Neural Text — The Qualifier That Couldn’t Share Its Name
CaseHub Neural Text — The Layer That Gives Floats Meaning
CaseHub Neural Text — The SPI That Argued Back
Neural Text — The Native Image Gate