The Proxy and the Bean

A static ThreadLocal on an @ApplicationScoped bean sidesteps @RequestScoped's dependency on an active HTTP context, making @ProvenanceCapture work in scheduled jobs and @QuarkusTest without a runti...

Cleaning House Before the Merge

Applying the squash policy to two live PRs collapses docs follow-on commits and surfaces a hitchhiker commit that snuck in under a different author's PR.

What Kind of Message Is This?

Adding MessageType to CaseChannelProvider.postToChannel forces a dependency graph decision: the engine takes a narrow compile dependency on casehub-qhorus-api rather than inventing a parallel vocab...

Two Models for Trust

Dimension scores are continuous magnitudes, not binary verdicts, so they need a decay-weighted average rather than a Beta accumulator — passing AttestationVerdict.SOUND forces pure time decay and d...

The Coherence Invariant

A channel can have at most one HumanParticipatingChannelBackend — enforced as a hard constraint at registration — because two human participants on different platforms produce two independent conve...

Server-sent events and two silent failures

Both SSE failures return HTTP 200 with valid-looking data — one because Quarkus adds the data: prefix Claudony was also adding, and one because a static ObjectMapper has no JavaTimeModule and silen...

When the Papers Disagree

Three peer-reviewed papers reach three incompatible conclusions on global trust aggregation — the right answer is a pluggable GlobalScoreStrategy SPI rather than picking one framework's position.

Platform Positioning and Incremental Build

Scoring ten use-case candidates across separate market-fit and community-fit tables reveals AML as the strongest entry point — Java is banking, banking is compliance infrastructure, and developers ...

The Body of Work

Reading normative-layer.md, agent-mesh-framework.md, and work-and-workitems.md together confirms vertical coherence — each layer addresses a distinct concern, with SUSPENDED and sub-delegation corr...

Scoped Trust

Every Qhorus attestation was landing on the global "*" capability tag, collapsing capability-scoped Beta distributions into one number — a two-method fix routes attestations to the correct scope by...

Docs That Build Themselves

Writing the developer guide reveals a missing tool — get_obligation_activity — because Part 6 keeps circling the same question: how do you see everything one obligation touched across all three cha...

Workers can finally talk back

The CaseChannelProvider.postToChannel path existed but was never connected — WorkerContext.channels was always empty, and the buildContext() result was silently discarded before workers were schedu...

What Polling Was Hiding

Switching from polling to server-initiated push exposes three guarantees polling provided for free — restart resilience, catch-up, and identity — that each require deliberate design in a push model.

Two Bugs That Looked Wrong

Both failing tests present misleading symptoms — the watchdog test counts two alerts because the scheduler runs on a separate thread that can see committed test data, not because evaluateAll() was ...

Three bugs hiding behind the wrong error

The BackPressureFailure filling the CI log is noise — the actual failure is an OptimisticLockException buried further down, caused by the M-of-N coordinator racing against itself during concurrent ...

The Sentinel, This Time

For capabilityTag, the sentinel "*" is the right answer where NULL was right for scope_key — query patterns use the same operator as any scoped query, and every major policy system already uses "*"...

CI Chain Repair

The cross-repo dispatch never fired because GITHUB_TOKEN is scoped to the repo where the workflow runs — six repos needed a PAT, and the CI UI was showing success for failed steps because continue-...

Platform-Wide Breaking Window

A casehub-engine release window triggers twenty-one tasks across five repos in one session — breaking MCP renames, module splits to stop JPA entities leaking onto test classpaths, and a naming audi...

Three audit findings and a wrong mental model

Three audit findings include a String.format JSON builder that silently corrupts output on non-trivial actor IDs, a bug the auditor described with the wrong mechanism, and a Bayesian mental model e...

Distributed SSE and the infrastructure tax

Redis for distributed SSE fan-out is rejected because it would force two new infrastructure pieces on users who have neither Redis nor MongoDB — a pluggable WorkItemEventBroadcaster SPI defers the ...

Phase 15: Auditing the Audit Trail

An external audit finds two production bugs in ClaudonyLedgerEventCapture: a swallowed persistence exception that silently drops ledger entries, and a MAX() sequence query with no UNIQUE constraint...

What the Reviews Missed

Five deferred issues ship in one push, but the session's main discovery is that a sentinel empty-string for global scope was unnecessary — the previous session already solved the uniqueness constra...

Phase 14: The Panel Knows Its Case

Adding caseId and roleName to the immutable Session record touches 20+ construction sites, and the left panel auto-expands with clickable worker rows that reconnect the WebSocket without reloading ...

Migration Gaps Closed

Idempotency window, DLQ replay, and SubCaseBinding close the last migration gaps, but a transitive quarkus-ledger dependency bundles JPA entities into every module that touches engine and breaks fo...

Worker registration as a speech act

WorkerRegistry becomes the single source of truth for all three worker entry paths — static, provisioned, self-registering — and Java 21 sealed classes provide the execution fork without an explici...

What the Channel Allows

The allowed_types field enforces NormativeChannelLayout at the infrastructure level, and a production bug hiding behind test infrastructure surfaces — a @TestTransaction isolation gap was letting t...

Six Ways to Query an Obligation

Six new query tools give the normative ledger its first analytical surface — get_obligation_chain computes participant order and handoff count that cannot be extracted from a single list_ledger_ent...

Connecting quarkus-work to the blackboard

CaseLifecycleEvent gets its missing worker execution call sites, and the casehub-work-adapter uses CDI choreography to route quarkus-work terminal states into PlanItem transitions via the callerRef...

SLAs, signals, and a connector library

Business-hours SLA and outbound notifications ship, and a notification routing detail that starts as a one-line decision grows into casehub-connectors — a separate repository born from the question...

The name problem hiding an identity problem

CaseHub uses worker roles while Claudony tracks session UUIDs — WorkerSessionMapping bridges the two identity systems, with a documented MVP limitation when concurrent same-role workers share a case.

CommitmentStore Ships

PendingReply was always instantiating Singh's social commitment model for the QUERY→RESPONSE case — CommitmentStore completes the picture with seven states covering every path a QUERY or COMMAND ca...

The primitive and the orchestrator

A data-driven spawn rule table is rejected before a line of code — the right answer is that subprocess orchestration belongs to CaseHub, and quarkus-work should expose the primitive that CaseHub re...

Jlama Fixed, CI Housekeeping

Fixing Jlama takes four cascading commits — the ARM_128 UnsupportedOperationException surfaces only after the boot crash is fixed, and requires the native Apple Silicon library rather than the Java...

The config mapping trap

The four CaseHub SPIs wire up cleanly, but @ConfigMapping strict validation fires before library roots register and CaseLedgerEntryRepository turns out not to be a CDI bean despite looking exactly ...

The Fix That Would Have Broken Everything

A plausible commit hardcodes @PersistenceUnit("qhorus") into a generic extension library — caught in git log review before it shipped, with the correct fix being a DefaultBean producer pattern in t...

Speech-Act Taxonomy Ships

Four research passes through Austin, Searle, FIPA, Singh, and Governatori ground the nine-type taxonomy in a formal obligation lifecycle — each type creates, discharges, or transfers exactly one ki...

A rule, not a preference

Migrating Qhorus to a named datasource hardens into an ecosystem-wide rule — every library owns a named datasource matching its artifact ID — and exposes two direct EntityManager calls hiding behin...

Trust Without Memory

W3C PROV-DM, NIST AI standards, and multi-agent framework research converge on the same answer for LLM agent identity: a stable dereferenceable URI bound to the system configuration, not the session.

The substrate and what grows on it

Splitting quarkus-work-api into pure contract and quarkus-work-core with CDI implementations reveals that WorkBroker and WorkItems are specialisations of a shared Work substrate that CaseHub also n...

Named Datasources and a Rogue Agent

Migrating to a named datasource exposes an inheritance constraint — AgentMessageLedgerEntry and LedgerEntry must share a persistence unit — resolved by including the ledger package in Qhorus's pers...

When the Paper Is Wrong

Implementing EigenTrust transitivity reveals that the original paper's trust matrix normalisation produces incorrect results for pre-trusted peers — the fix derives from first principles rather tha...

Documentation That Lies

Rating each capability for enterprise applicability forces an honest assessment — EigenTrust transitivity earns two stars in 2026 not because it is wrong but because enterprise AI agent meshes have...

Forgiveness Was a Patch

The ForgivenessParams mechanism gets replaced entirely when Bayesian Beta replaces the coarse-grained scoring model — a principled prior that treats uncertainty correctly makes the forgiveness patc...

Ecosystem Mapping, PRs F-J, ADR-0002

Gap closure via PRs F through J expands into a fifteen-issue ecosystem map, and the binding-gating decision — presence of stage.addBinding() as the opt-in — is validated as the only bounded and fai...

Idle is not one thing

Three CDI-pluggable expiry policies distinguish an idle shell from an autonomously working agent, collected at startup via @Any Instance so new policies are just new beans.

The Reactive Dual-Stack Ships

The 39 MCP tools split into 20 pure reactive chains and 19 @Blocking delegates, with the QhorusMcpToolsBase extraction fixing a Java import limitation where inherited nested types cannot be importe...

QE Pass: 68 Tests to 99, Five PRs

A systematic comparison against the original implementation surfaces thread-safety gaps in PlanItem and Stage, missing end-to-end scenarios, and a null pointer hidden by the String constructor over...

The filter that grew into a contract

A confidence-gated routing rule that could be wired in twenty lines becomes quarkus-work-filter-registry instead — because inline logic is a trap that becomes load-bearing and unremovable.

No Panache in the Model

Stripping Panache from all extension entities removes a framework dependency consumers didn't choose, and @NamedQuery replaces the static Panache shorthand with startup-validated queries that fail ...

A Clean Entity

Converting LedgerEntry from PanacheEntityBase to a plain @Entity removes the Panache dependency that was blocking Qhorus's reactive migration and unblocks any future consumer choosing a different p...

Catching the Docs Before They Hit a Consumer

The Merkle sprint deleted LedgerHashChain without updating the integration guide, leaving consumers with compile-error-inducing sample code that pointed nowhere — a systematic cleanup removes every...

The Reactive Store Layer Ships

Issue #74 ships five reactive store interfaces and implementations via the subagent workflow — one issue per session after the planning tool hit the 32k output limit generating the full eight-issue...

Ledger Adaptation and the Dual-Stack Decision

quarkus-ledger ships dual blocking/reactive repositories, unlocking Qhorus's reactive migration — and AgentMessageLedgerEntryRepository switches from Panache statics to EntityManager injection to r...

The observer becomes a participant

A fixed send dock in all three mesh views lets humans post into any active channel without switching panels, turning the read-only mesh observer into an active participant.

Teaching the Ledger to Speak W3C

LedgerEntry exports as W3C PROV-JSON-LD per subject, deduplicating agents across entries and emitting both sequential and cross-subject wasDerivedFrom edges so regulators get a complete provenance ...

From O(N) to O(log N)

The Merkle Mountain Range structure from RFC 9162 provides O(log N) frontier storage and tamper-evident inclusion proofs signed with Ed25519, making verification genuinely independent of the operator.

Cutting the JPA Wire

PR3 strips JPA from the engine module entirely — three domain objects become plain Java, twelve handlers route through three SPI interfaces, and no framework annotation remains in casehub-core.

Two Fields in the Wrong Place

A research pass across ten directions produces an ADR grounding the forgiveness mechanism in two parameters — recency and frequency — after finding that severity double-counts a signal already pres...

Fleet Phase 2: the fleet you can see

Fleet Phase 2 adds the fleet sidebar and WebSocket proxy bridge, and the first Playwright test immediately finds a four-month-old bug hiding in displayName() that no one had noticed.

Examples that prove it

Four runnable examples — expense approval, regulated credit decision, AI content moderation, and document review — together exercise every ledger capability, and the agent: prefix convention derive...

The fleet was inevitable

Fleet Phase 1 extends Claudony to manage sessions across multiple instances — and clears three deferred embarrassments: a hardcoded encryption key committed to the repo, a 30-minute session timeout...

Phases 1–5: Building the Foundation

Zero Java to five complete phases in one session — BARRIER channel semantics, wait_for_reply with SSE keepalives, and artefact lifecycle — with code review catching a double-claim race and a UUID f...

Locking Down the Mesh

Write permissions, admin role, rate limiting, and observer mode land via strict TDD, with non-@Tool convenience overloads solving the AddParameter-breaks-existing-tests problem without duplicating ...

Phase 1: Into casehub-engine

The merge direction reversed before a single line of code was written. casehub-engine becomes the home; Phase 1 lays the extension points incrementally, one PR at a time.

From Addressing to Human Control

Forty-two commits close phases 6 through 10 — read-side dispatch filtering handles all three target modes in one private method, and human-in-the-loop approval gates move to quarkus-workitems as th...

Claudony — The Name That Fits

RemoteCC was always a placeholder — Claudony emerged from the colony metaphor and brought a bioluminescent visual language that makes the architecture literal.

Day Zero: Designing a Multi-Agent Mesh

Designing the Qhorus multi-agent mesh starts by studying A2A, ACP, AutoGen, LangGraph, and CrewAI — and deciding that Qhorus should be infrastructure orthogonal to all of them, not another orchestr...

Two CaseHubs, One Design

Discovering a parallel casehub-engine implementation and charting a 9-phase plan to unify both systems into one coherent design.