Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ nb-configuration.xml
# Local environment
.env

# Leaked build artifacts (class files, JAR manifests, properties)
/io/
/META-INF/
/application.properties

# Claude workflow docs
docs/superpowers/

# Plugin directory
/.quarkus/cli/plugins/
# TLS Certificates
Expand Down
14 changes: 7 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ The protocol asks: Does this already exist elsewhere? Is this the right repo for

**Platform architecture (fetch before any implementation decision):**
```
https://raw.githubusercontent.com/casehubio/casehub-parent/main/docs/PLATFORM.md
https://raw.githubusercontent.com/casehubio/parent/main/docs/PLATFORM.md
```

**This repo's deep-dive:**
```
https://raw.githubusercontent.com/casehubio/casehub-parent/main/docs/repos/casehub-engine.md
https://raw.githubusercontent.com/casehubio/parent/main/docs/repos/casehub-engine.md
```

**Other repo deep-dives** (fetch the relevant ones when your implementation touches their domain):
- casehub-ledger: `https://raw.githubusercontent.com/casehubio/casehub-parent/main/docs/repos/casehub-ledger.md`
- casehub-work: `https://raw.githubusercontent.com/casehubio/casehub-parent/main/docs/repos/casehub-work.md`
- casehub-qhorus: `https://raw.githubusercontent.com/casehubio/casehub-parent/main/docs/repos/casehub-qhorus.md`
- claudony: `https://raw.githubusercontent.com/casehubio/casehub-parent/main/docs/repos/claudony.md`
- casehub-connectors: `https://raw.githubusercontent.com/casehubio/casehub-parent/main/docs/repos/casehub-connectors.md`
- casehub-ledger: `https://raw.githubusercontent.com/casehubio/parent/main/docs/repos/casehub-ledger.md`
- casehub-work: `https://raw.githubusercontent.com/casehubio/parent/main/docs/repos/casehub-work.md`
- casehub-qhorus: `https://raw.githubusercontent.com/casehubio/parent/main/docs/repos/casehub-qhorus.md`
- claudony: `https://raw.githubusercontent.com/casehubio/parent/main/docs/repos/claudony.md`
- casehub-connectors: `https://raw.githubusercontent.com/casehubio/parent/main/docs/repos/casehub-connectors.md`

---

Expand Down
24 changes: 12 additions & 12 deletions adr/0003-work-workitem-task-naming.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ class with a `WorkerSelectionStrategy` SPI and a `TaskScheduler` for routing
work to workers. As part of the migration to casehub-engine, these concepts
must be re-implemented. In parallel, casehub-engine and quarkus-workitems
independently designed the same worker-selection SPI and aligned on a shared
`quarkus-work-api` library — which uses `WorkBroker`, `WorkerSelectionStrategy`,
`casehub-work-api` library — which uses `WorkBroker`, `WorkerSelectionStrategy`,
and `WorkerCandidate` as its canonical names. Issue #121 captured this design
using `TaskBroker` as a working name. This ADR closes that open naming
decision: casehub-core's `TaskBroker` is not ported; `WorkBroker` from
quarkus-work-api is adopted as its replacement.
casehub-work-api is adopted as its replacement.

## Decision Drivers

* `quarkus-work-api` already uses `Work`-prefixed names — adopting them
* `casehub-work-api` already uses `Work`-prefixed names — adopting them
directly eliminates any translation layer between casehub-engine and the
shared SPI
* `WorkItem` has well-understood human-inbox connotations (Jira, Azure DevOps)
Expand All @@ -30,23 +30,23 @@ quarkus-work-api is adopted as its replacement.
## Considered Options

* **Option A — `Work` + `WorkItem` + `Task`**: three-level hierarchy, aligned
with quarkus-work-api
with casehub-work-api
* **Option B — Unified `WorkItem`**: everything is a WorkItem; automated tasks
are `AutomatedWorkItem`, human tasks are `HumanWorkItem`
* **Option C — Introduce `TaskBroker`**: use the working name from #121;
accept mismatch with quarkus-work-api
accept mismatch with casehub-work-api

## Decision Outcome

Chosen option: **Option A**, because it maps exactly onto the quarkus-work-api
Chosen option: **Option A**, because it maps exactly onto the casehub-work-api
naming already agreed with treblereel, and gives each term a precise,
non-overlapping meaning.

### Positive Consequences

* `WorkBroker` from `quarkus-work-core` replaces casehub-core's `TaskBroker`
* `WorkBroker` from `casehub-work-core` replaces casehub-core's `TaskBroker`
with no port required — the shared SPI is the implementation
* casehub-core's `WorkerSelectionStrategy` maps directly to quarkus-work-api's
* casehub-core's `WorkerSelectionStrategy` maps directly to casehub-work-api's
`WorkerSelectionStrategy` — same interface, aligned name
* `WorkItem` retains its human-inbox specialisation in the WorkItems module
* `Task` is reserved for sub-steps within a `Work` unit — unambiguous scope
Expand All @@ -63,7 +63,7 @@ non-overlapping meaning.

### Option A — `Work` + `WorkItem` + `Task`

* ✅ Zero translation layer against quarkus-work-api
* ✅ Zero translation layer against casehub-work-api
* ✅ `WorkItem` retains its precise human-inbox meaning
* ✅ `Task` is unambiguous at sub-step level
* ❌ `Work` as a top-level noun needs explicit documentation
Expand All @@ -72,16 +72,16 @@ non-overlapping meaning.

* ✅ Single concept for everything assignable
* ❌ Conflicts with established tooling connotations
* ❌ Mismatches quarkus-work-api — requires a translation layer
* ❌ Mismatches casehub-work-api — requires a translation layer

### Option C — Introduce `TaskBroker`

* ✅ Consistent with #121 working name
* ❌ Permanent mismatch with quarkus-work-api
* ❌ Permanent mismatch with casehub-work-api
* ❌ Introduces debt from day one; would require renaming later

## Links

* casehubio/engine#121 — open design issue whose naming decision this ADR closes
* `io.quarkiverse.work:quarkus-work-api` — shared SPI whose naming this ADR adopts
* `io.casehub:casehub-work-api` — shared SPI whose naming this ADR adopts
* ADR-0001, ADR-0002 — prior casehub-engine decisions (blackboard series)
2 changes: 1 addition & 1 deletion casehub-work-adapter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<artifactId>casehub-engine-work-adapter</artifactId>
<name>Case Hub :: Work Adapter</name>
<description>Bridge between quarkus-work WorkItemLifecycleEvent and CaseHub's blackboard PlanItem lifecycle</description>
<description>Bridge between casehub-work WorkItemLifecycleEvent and CaseHub's blackboard PlanItem lifecycle</description>

<dependencies>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* <p>Format: {@code case:{caseId}/pi:{planItemId}}
*
* <p>CaseHub owns the semantics of this opaque string — quarkus-work stores it unchanged on the
* WorkItem and echoes it back in every WorkItemLifecycleEvent. Refs casehubio/quarkus-work#136.
* WorkItem and echoes it back in every WorkItemLifecycleEvent. Refs casehubio/work#136.
*/
public record CallerRef(UUID caseId, String planItemId) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
* transitions and fires {@code CONTEXT_CHANGED} to trigger engine re-evaluation.
*
* <p>Choreography path: the engine's binding evaluator picks up the next step automatically once
* the PlanItem status changes and the context-changed signal arrives. Refs
* casehubio/quarkus-work#136.
* the PlanItem status changes and the context-changed signal arrives. Refs casehubio/work#136.
*
* <p>Only processes events whose {@code callerRef} matches the CaseHub format {@code
* case:{caseId}/pi:{planItemId}} — other WorkItems are ignored.
Expand Down
8 changes: 4 additions & 4 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ Lifecycle handlers fire `CaseLifecycleEvent` via `Event.fireAsync()` after their

### Audit Ledger (`casehub-ledger`, optional)

An optional module that writes an immutable, hash-chained audit record for every significant case lifecycle transition. Depends on `engine-model` (for `CaseLifecycleEvent`) and `quarkus-ledger` — no dependency on the `engine` module itself.
An optional module that writes an immutable, hash-chained audit record for every significant case lifecycle transition. Depends on `engine-model` (for `CaseLifecycleEvent`) and `casehub-ledger` — no dependency on the `engine` module itself.

| Class | Role |
|---|---|
| `CaseLedgerEntry` | `LedgerEntry` subclass (JOINED inheritance) — adds `caseId`, `commandType`, `eventType`, `caseStatus` |
| `CaseLedgerEntryRepository` | Extends `JpaLedgerEntryRepository`; `@ApplicationScoped` activates it as the CDI `LedgerEntryRepository` bean |
| `CaseLedgerEventCapture` | `@ObservesAsync CaseLifecycleEvent` — writes entry in its own `@Transactional` block on a managed executor thread |

**Flyway migration:** V2000 (`case_ledger_entry` table + FK to `ledger_entry`). V1000–V1004 are reserved by quarkus-ledger.
**Flyway migration:** V2000 (`case_ledger_entry` table + FK to `ledger_entry`). V1000–V1004 are reserved by casehub-ledger.

**Observed transitions:**

Expand Down Expand Up @@ -437,6 +437,6 @@ Entries that exhaust max-attempts stay PENDING_REVIEW for manual triage.
- **ADR-0003** — Work/WorkItem/Task naming hierarchy
- **casehubio/engine#121** — Original design discussion (closed by ADR-0003)
- **casehubio/engine#131** — WorkBroker integration epic
- **casehubio/engine#145** — quarkus-ledger integration epic
- **casehubio/engine#145** — casehub-ledger integration epic
- **casehubio/engine#191** — Worker Provisioner SPI wiring
- **mdproctor/quarkus-ledger#39** — CaseLedgerEntry tracking issue
- **mdproctor/casehub-ledger#39** — CaseLedgerEntry tracking issue
Loading
Loading