Skip to content

epic: complete causal lineage across all execution boundaries #205

@mdproctor

Description

@mdproctor

Summary

Ensures every unit of work at every level emits a CaseLedgerEntry node so causedByEntryId chains are traversable end-to-end. Introduces SPAWN_STARTED / SPAWN_COMPLETED as unified ledger event types replacing the per-model family of SUBCASE_STARTED, WORKFLOW_STEP_DISPATCHED, PLAN_STEP_STARTED, etc.

Consolidation — unified SPAWN event types

All spawning operations share identical ledger structure: parentLedgerEntryId, childId, spawnType, returnTo, policy. Instead of N event types with per-type metadata:

CaseHubEventType.SPAWN_STARTED   // replaces SUBCASE_STARTED, WORKFLOW_STEP_DISPATCHED,
                                  //   PLAN_STEP_STARTED, AGENT_INVOCATION_STARTED,
                                  //   WORKITEM_CHILD_CREATED
CaseHubEventType.SPAWN_COMPLETED  // replaces SUBCASE_COMPLETED, etc.

Standard metadata fields (all SPAWN_STARTED entries carry these):

  • spawnType: SUBCASE | WORKFLOW_STEP | PLAN_STEP | AGENT_INVOCATION | WORKITEM_CHILD | WORKITEM_GROUP
  • childId — what was spawned
  • returnTo — where output routes back
  • policyType — ALL | M_OF_N | FIRST | ANY
  • policyThreshold — for M_OF_N
  • groupId — groups parallel spawns (same value for all children in a multi-instance group)

Lineage traversal becomes uniform: every node is SPAWN_STARTED / SPAWN_COMPLETED, regardless of what was spawned. findCausalChain() queries one event type, not N.

Current partial state

SpawnRecord

CompletionTracker (epic #204) creates a SpawnRecord for each SPAWN_STARTED entry:

record SpawnRecord(
    UUID spawnId,
    UUID parentLedgerEntryId,
    SpawnType type,
    List<UUID> childIds,
    Object returnTo,
    CompletionPolicy policy,
    int threshold
) {}

The SpawnRecord is the runtime counterpart to the ledger entry — the tracker holds it in memory; the ledger entry is the durable record.

Lineage query API

interface LineageRepository {
    CausalGraph findCausalChain(UUID rootEntryId, int maxDepth);
    List<CaseLedgerEntry> findDirectChildren(UUID spawnStartedEntryId);
    List<CaseLedgerEntry> findRootCauses(UUID caseId);
    List<CaseLedgerEntry> findByGroup(UUID groupId);  // all children in a multi-instance group
}

quarkus-work multi-instance

Part of

#201

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestepicTracks a large body of related work

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions