diff --git a/.github/workflows/chain-canary.yml b/.github/workflows/chain-canary.yml index 77e26c0a15..dc4b4171cf 100644 --- a/.github/workflows/chain-canary.yml +++ b/.github/workflows/chain-canary.yml @@ -376,8 +376,19 @@ jobs: # a chain short by a hop must not look complete simply because every # row present was well-formed. These are the ordered topics one # delegation traverses, per the node contracts that publish them. + # + # OMN-18419 adds delegation-request.v1, the pattern-B worker command + # the runtime's delegation dispatch port publishes while consuming + # the delegate-skill command. It was always traversed and never + # declared, so the routing request's recorded causal parent named an + # envelope that was not in the chain. These five must stay equal to + # node_delegation_chain_ledger_effect's `chain_topology` topics, in + # order: that contract is the writer's authority and this list is the + # reader's, and a chain graded against one and checked against the + # other is two declarations free to disagree. EXPECTED_LEDGER_HOPS: >- onex.cmd.omnimarket.delegate-skill.v1, + onex.cmd.omnibase-infra.delegation-request.v1, onex.cmd.omnibase-infra.delegation-routing-request.v1, onex.evt.omnibase-infra.routing-decision.v1, onex.evt.omnimarket.delegate-skill-completed.v1 diff --git a/scripts/check_subscribe_wiring_health.py b/scripts/check_subscribe_wiring_health.py index b2372be3f8..58f38d7eab 100644 --- a/scripts/check_subscribe_wiring_health.py +++ b/scripts/check_subscribe_wiring_health.py @@ -142,6 +142,15 @@ "onex.cmd.omnimarket.delegate-skill.v1": "Published by omnimarket node_delegate_skill_orchestrator (command_topic, contract.yaml:220), cross-repo | owner: jonah | expiry: 2026-12-01", "onex.cmd.omnibase-infra.delegation-routing-request.v1": "Published by omnimarket node_delegation_orchestrator (contract.yaml:148), cross-repo | owner: jonah | expiry: 2026-12-01", "onex.evt.omnibase-infra.routing-decision.v1": "Published by omnimarket node_delegation_routing_reducer as its success terminal (contract.yaml:87), cross-repo | owner: jonah | expiry: 2026-12-01", + # OMN-18419: the fifth delegation-chain hop. Unlike the four above it is + # published from THIS repository, but not by a contract-declared publisher + # a scan of `publish_topics` can see: RuntimePatternBBroker publishes it as + # `route.command_topic`, and the route is DISCOVERED at runtime from + # omnimarket node_delegation_orchestrator's own subscribe_topics + # (service_delegation_dispatch_port.py). The topic string appears in no + # publish_topics list anywhere, which is why it needs an entry here rather + # than a contract fix. + "onex.cmd.omnibase-infra.delegation-request.v1": "Published by RuntimePatternBBroker as the runtime-discovered route.command_topic for node_delegation_orchestrator (service_delegation_dispatch_port.py), never declared in a publish_topics list | owner: jonah | expiry: 2026-12-01", } # --------------------------------------------------------------------------- diff --git a/src/omnibase_infra/enums/generated/enum_omnibase_infra_topic.py b/src/omnibase_infra/enums/generated/enum_omnibase_infra_topic.py index 3aaf859b23..577f62e91b 100644 --- a/src/omnibase_infra/enums/generated/enum_omnibase_infra_topic.py +++ b/src/omnibase_infra/enums/generated/enum_omnibase_infra_topic.py @@ -25,6 +25,7 @@ class EnumOmnibaseInfraTopic(str, Enum): CMD_CODING_AGENT_INVOKE_V1 = "onex.cmd.omnibase-infra.coding-agent-invoke.v1" # onex.cmd.omnibase-infra.coding-agent-invoke.v1 CMD_CODING_AGENT_WORKSPACE_VALIDATE_V1 = "onex.cmd.omnibase-infra.coding-agent-workspace-validate.v1" # onex.cmd.omnibase-infra.coding-agent-workspace-validate.v1 CMD_CONSUMER_RESTART_V1 = "onex.cmd.omnibase-infra.consumer-restart.v1" # onex.cmd.omnibase-infra.consumer-restart.v1 + CMD_DELEGATION_REQUEST_V1 = "onex.cmd.omnibase-infra.delegation-request.v1" # onex.cmd.omnibase-infra.delegation-request.v1 CMD_DELEGATION_ROUTING_REQUEST_V1 = "onex.cmd.omnibase-infra.delegation-routing-request.v1" # onex.cmd.omnibase-infra.delegation-routing-request.v1 CMD_FAULT_INJECT_FIXTURE_V1 = "onex.cmd.omnibase-infra.fault-inject-fixture.v1" # onex.cmd.omnibase-infra.fault-inject-fixture.v1 CMD_GATEWAY_ATTACH_REQUEST_V1 = "onex.cmd.omnibase-infra.gateway-attach-request.v1" # onex.cmd.omnibase-infra.gateway-attach-request.v1 diff --git a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/chain_replay.py b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/chain_replay.py index b05238bd01..d02c2eeca4 100644 --- a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/chain_replay.py +++ b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/chain_replay.py @@ -14,11 +14,36 @@ WHAT "REPLAY" MEANS HERE, STATED PLAINLY ---------------------------------------- It is a re-derivation of the chain's CAUSAL LINKAGE from the recorded -envelopes, compared against what was recorded. For each hop after the head, -the expected parent envelope id is recomputed from the preceding observed hop -and compared to the parent the envelope actually carries; the correlation id -on each hop is compared to the chain's own. A hop replays green only when both -re-derivations reproduce. +envelopes, compared against what was recorded. For each hop, the expected +parent is resolved from the DECLARED topology -- the hop whose consumption the +contract says causes this one -- and the envelope id observed on that declared +parent topic is compared to the parent the envelope actually carries; the +correlation id on each hop is compared to the chain's own. A hop replays green +only when both re-derivations reproduce. + +THE DECLARED TOPOLOGY IS A TREE, AND THAT IS NOT A DETAIL (OMN-18419) +-------------------------------------------------------------------- +Until OMN-18419 the expected parent was recomputed from ``observed[index - 1]`` +-- the hop that happened to precede this one in time. That is correct for a +LINE and wrong for anything else, and the chain this module grades is a TREE. +Measured read-only on the .201 compose dev lane, correlation +``41235987-425c-481b-b2e3-8970083ce512`` (chain-canary run 35037024216): +``delegate-skill-completed`` records the ``delegate-skill`` COMMAND envelope as +its parent, because it is a consequence of consuming that command and not of +the routing decision that preceded it in time. The recorded edge was right; the +positional re-derivation was wrong; a correct chain graded red. + +So the parent relation is now DECLARED, one entry per hop +(``ModelDeclaredChainHop``), and the replay grades each recorded edge against +the hop the declaration names. Nothing about this particular canary is +special-cased: a line is a tree whose every parent is the preceding hop, and it +grades identically under both readings. + +A consequence worth stating because it changes a verdict: the replay now needs +the declaration. With no declaration reaching a hop there is nothing to +re-derive FROM, so that hop replays RED with a stated reason -- it does not +fall back to the positional guess and it does not report green. This is the +same rule tier 2 already held: a check that could not run has not passed. It is deliberately NOT a re-execution of the delegation's inference. One hop of this chain calls a language model, which is not a deterministic function, so a @@ -63,6 +88,9 @@ from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.enum_tier_two_verdict import ( EnumTierTwoVerdict, ) +from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.model_declared_chain_hop import ( + ModelDeclaredChainHop, +) from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.model_ledger_chain_row import ( ModelLedgerChainRow, ) @@ -75,17 +103,41 @@ "SKIP is not PASS" ) +_NO_DECLARED_PARENT_DETAIL = ( + "no declared chain topology names this hop, so there is no parent " + "relation to re-derive the causal edge from; a check that could not run " + "has not passed" +) + + +def _declared_hop_for( + topic: str, declared_chain: Sequence[ModelDeclaredChainHop] +) -> ModelDeclaredChainHop | None: + """Return the declaration for ``topic``, or None when none names it. + + Resolved by TOPIC, not by position. Position is tier 2's question ("is the + observed chain the declared chain?"), and answering it twice from two + places would let the two tiers disagree about what a hop IS. Tier 1 asks + only whether the recorded causal edge closes, which is a statement about + this hop's identity and not about where it sits. + """ + for candidate in declared_chain: + if candidate.topic == topic: + return candidate + return None + def _replay_one_hop( index: int, hop: ModelObservedHop, - previous: ModelObservedHop | None, + observed: Sequence[ModelObservedHop], + declared_chain: Sequence[ModelDeclaredChainHop], correlation_id: UUID, ) -> tuple[bool, str]: """Re-derive this hop's linkage and compare it to what was recorded. Returns ``(replay_green, detail)``. ``detail`` is EMPTY exactly when the - replay was green — a green carrying an explanation would suggest the check + replay was green -- a green carrying an explanation would suggest the check was hedged. """ if hop.correlation_id is not None and hop.correlation_id != correlation_id: @@ -98,18 +150,61 @@ def _replay_one_hop( ), ) - if previous is None: - # The head of the chain has no predecessor. There is nothing to - # re-derive, and nothing is claimed beyond the two checks above. + declared = _declared_hop_for(hop.topic, declared_chain) + if declared is None: + return False, _NO_DECLARED_PARENT_DETAIL + + if declared.parent is None: + # The declaration says this hop is the chain HEAD. That is a claim with + # a falsifier, not a free pass: a head that records a parent is either a + # mis-declared topology or a hop that is not actually the head. + if hop.parent_envelope_id is not None: + return ( + False, + ( + f"the declared topology makes {hop.topic!r} the chain head, " + f"but this hop records parent {hop.parent_envelope_id!r} — " + "a head has no cause to point at" + ), + ) return True, "" - expected_parent = previous.envelope_id - if hop.parent_envelope_id != expected_parent: + # A redelivery is projected as a second row carrying the SAME deterministic + # envelope id, so the declared parent topic can legitimately appear more + # than once. Matching against ANY of them is not a loosening: the edge is + # checked against a concrete observed envelope id either way. + candidates = tuple( + candidate.envelope_id + for candidate in observed + if candidate.topic == declared.parent + ) + if not candidates: + return ( + False, + ( + f"the declared parent of {hop.topic!r} is {declared.parent!r}, " + "which was not observed on this correlation — the causal edge " + "cannot be re-derived from evidence that is not there" + ), + ) + + if hop.parent_envelope_id is None: + return ( + False, + ( + f"this hop records no parent, which is the checkable statement " + f"that it is a chain HEAD, but the declared topology says " + f"{hop.topic!r} is caused by {declared.parent!r} " + f"(observed as {candidates[0]!r}) — the causal edge does not close" + ), + ) + + if hop.parent_envelope_id not in candidates: return ( False, ( - f"parent re-derives to {expected_parent!r} from the preceding " - f"hop {previous.topic!r}, but this hop records " + f"the declared parent {declared.parent!r} was observed as " + f"{list(candidates)!r}, but this hop records " f"{hop.parent_envelope_id!r} — the causal link does not close" ), ) @@ -120,7 +215,7 @@ def _replay_one_hop( def _verify_one_hop( index: int, hop: ModelObservedHop, - declared_chain: Sequence[str], + declared_chain: Sequence[ModelDeclaredChainHop], ) -> tuple[EnumTierTwoVerdict, str]: """Tier 2: does this observation match the DECLARED topology at this position? @@ -131,7 +226,7 @@ def _verify_one_hop( if index >= len(declared_chain): return EnumTierTwoVerdict.SKIP, _NO_DECLARATION_DETAIL - expected_topic = declared_chain[index] + expected_topic = declared_chain[index].topic if hop.topic == expected_topic: return EnumTierTwoVerdict.PASS, "" @@ -147,7 +242,7 @@ def _verify_one_hop( def assemble_replay_and_verify( correlation_id: UUID, observed: Sequence[ModelObservedHop], - declared_chain: Sequence[str], + declared_chain: Sequence[ModelDeclaredChainHop], ) -> tuple[ModelLedgerChainRow, ...]: """Turn observed envelopes into replayed, tier-2-verified ledger rows. @@ -155,10 +250,13 @@ def assemble_replay_and_verify( function does not reorder it, because the observed order IS the evidence and sorting it would erase a transposition that tier 2 exists to catch. - ``declared_chain`` is the tier-2 authority: the ordered topics the node - contracts say a delegation traverses. An EMPTY declaration is legitimate - and yields SKIP on every row — the canary then reports VERIFIER_SKIPPED, - which is red. It is never treated as "nothing to check, therefore fine". + ``declared_chain`` is the authority for BOTH tiers: the ordered hops the + node contracts say a delegation traverses, each naming the declared topic + that causes it. Tier 2 reads the ORDER; tier 1 reads the PARENT RELATION. + An EMPTY declaration is legitimate and yields SKIP on every tier-2 row and + a stated-reason RED on every tier-1 row — the canary then reports + VERIFIER_SKIPPED, which is red. It is never treated as "nothing to check, + therefore fine". An empty ``observed`` returns zero rows rather than any synthetic row. The canary computes ``all(row.replay_green for row in rows)``, which is @@ -166,11 +264,10 @@ def assemble_replay_and_verify( separately; a single fabricated green row here would defeat that guard. """ rows: list[ModelLedgerChainRow] = [] - previous: ModelObservedHop | None = None for index, hop in enumerate(observed): replay_green, replay_detail = _replay_one_hop( - index, hop, previous, correlation_id + index, hop, observed, declared_chain, correlation_id ) verdict, verifier_detail = _verify_one_hop(index, hop, declared_chain) @@ -188,7 +285,6 @@ def assemble_replay_and_verify( verifier_detail=verifier_detail, ) ) - previous = hop return tuple(rows) diff --git a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/contract.yaml b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/contract.yaml index b59e77e07f..1c3649fdc7 100644 --- a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/contract.yaml +++ b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/contract.yaml @@ -7,11 +7,11 @@ runtime_profiles: - effects contract_version: major: 1 - minor: 0 - patch: 1 -node_version: "0.1.1" + minor: 1 + patch: 0 +node_version: "0.2.0" description: > - Records a correlation-scoped delegation chain after its terminal event. The handler reads envelope identity and parent identity from event_ledger, re-derives every causal edge, verifies the observed topics against this contract's declared topology, and idempotently writes public.ledger_chain. A write that cannot happen is a typed failure, never a success (OMN-18398): when the event_ledger read yields no hop at all on any topic in chain_topology, the handler refuses with a typed error naming the correlation id, the topics it looked for and the settle attempts it made, rather than reporting success having written nothing. A PARTIAL observation is still persisted as-is -- absence of a hop is honest evidence the canary reports as an incomplete chain, while absence of a whole chain is a success verdict resting on nothing. Each upsert is additionally required to affect a row: the statement always touches exactly one, so a zero count means the row this node claims to have recorded is not in the relation. + Records a correlation-scoped delegation chain after its terminal event. The handler reads envelope identity and parent identity from event_ledger, re-derives every causal edge against the parent this contract DECLARES for each hop (the chain is a tree, so a positional re-derivation grades a correct edge red -- OMN-18419), verifies the observed topics against this contract's declared topology, and idempotently writes public.ledger_chain. A write that cannot happen is a typed failure, never a success (OMN-18398): when the event_ledger read yields no hop at all on any topic in chain_topology, the handler refuses with a typed error naming the correlation id, the topics it looked for and the settle attempts it made, rather than reporting success having written nothing. A PARTIAL observation is still persisted as-is -- absence of a hop is honest evidence the canary reports as an incomplete chain, while absence of a whole chain is a success verdict resting on nothing. Each upsert is additionally required to affect a row: the statement always touches exactly one, so a zero count means the row this node claims to have recorded is not in the relation. input_model: name: "ModelDelegationTerminalPayload" @@ -35,14 +35,41 @@ handler_routing: module: "omnibase_infra.nodes.node_delegation_chain_ledger_effect.handlers.handler_delegation_chain_ledger" supported_operations: - "delegation_chain.record" -# Tier-2 authority. These are the ordered topics declared by the four -# participating node contracts. The handler reads this list from this file; +# The declared authority for BOTH tiers. The handler reads this from this file; # it does not infer the expected chain from the rows that happened to arrive. +# +# `parent` is the DECLARED TOPIC of the hop whose consumption causes this one, +# and it is what makes this a TREE rather than a line (OMN-18419). Tier 2 reads +# the ORDER of these entries; tier 1 reads the PARENT RELATION. Before the +# parent relation was declared, tier 1 re-derived each hop's expected parent +# from whatever sat at `index - 1`, which is correct only for a line -- and +# `delegate-skill-completed` branches off the head, because it is a consequence +# of consuming the delegate-skill COMMAND and not of the routing decision that +# preceded it in time. A correct chain therefore graded red. +# +# `parent: null` on the first entry is the checkable claim "this hop is the +# chain HEAD" -- the same claim an absent `parent_message_id` makes on the wire. +# The replay refuses a declared head that records a parent. +# +# The `delegation-request.v1` hop is DECLARED here rather than skipped over. +# It is the pattern-B worker command the runtime's delegation dispatch port +# publishes while consuming the delegate-skill command, and it is the real +# recorded parent of the routing request. Leaving it out would have forced the +# routing request to name a grandparent it never carried on the wire, which is +# a chain graded against a topology that did not happen. Its hop is projected +# into `event_ledger` by node_ledger_projection_compute's contract 1.4.0. chain_topology: - - "onex.cmd.omnimarket.delegate-skill.v1" - - "onex.cmd.omnibase-infra.delegation-routing-request.v1" - - "onex.evt.omnibase-infra.routing-decision.v1" - - "onex.evt.omnimarket.delegate-skill-completed.v1" + - topic: "onex.cmd.omnimarket.delegate-skill.v1" + parent: null + - topic: "onex.cmd.omnibase-infra.delegation-request.v1" + parent: "onex.cmd.omnimarket.delegate-skill.v1" + - topic: "onex.cmd.omnibase-infra.delegation-routing-request.v1" + parent: "onex.cmd.omnibase-infra.delegation-request.v1" + - topic: "onex.evt.omnibase-infra.routing-decision.v1" + parent: "onex.cmd.omnibase-infra.delegation-routing-request.v1" + # The branch. Observed last in time, caused by the head. + - topic: "onex.evt.omnimarket.delegate-skill-completed.v1" + parent: "onex.cmd.omnimarket.delegate-skill.v1" writer: settle_attempts: 20 settle_delay_ms: 250 @@ -66,9 +93,9 @@ metadata: description: "Evidence-derived writer for OMN-16025 chain-canary link 5." author: "OmniNode Team" created: "2026-09-13" - updated: "2026-09-15" + updated: "2026-09-16" ticket: "OMN-16964" - note: "OMN-18390: output_model dropped -- nothing consumed ModelLedgerChainWriteResult and the node has no publish_topics, so every declared output dead-lettered. OMN-18398: contract 1.0.1 records the refusal semantics above. The evidence this node reads is written only by node_ledger_projection_compute, whose subscription carried none of the four chain_topology topics below -- so the read was empty by construction and public.ledger_chain held zero rows on the .201 dev lane while this node reported success on every dispatch. That node's contract 1.3.0 now records and dispatches all four." + note: "OMN-18390: output_model dropped -- nothing consumed ModelLedgerChainWriteResult and the node has no publish_topics, so every declared output dead-lettered. OMN-18398: contract 1.0.1 records the refusal semantics above. The evidence this node reads is written only by node_ledger_projection_compute, whose subscription carried none of the four chain_topology topics below -- so the read was empty by construction and public.ledger_chain held zero rows on the .201 dev lane while this node reported success on every dispatch. That node's contract 1.3.0 now records and dispatches all four. OMN-18419: contract 1.1.0 turns chain_topology from an ordered list of topics into an ordered list of hops that each declare their parent topic, because the chain is a tree -- delegate-skill-completed branches off the head -- while the replay re-derived a line and graded the correct edge red. The same revision declares the delegation-request.v1 hop, which was always on the wire and never in the declaration." tags: - "effect" - "delegation" diff --git a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/handlers/handler_delegation_chain_ledger.py b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/handlers/handler_delegation_chain_ledger.py index 1715f0d301..1d3105b3c8 100644 --- a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/handlers/handler_delegation_chain_ledger.py +++ b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/handlers/handler_delegation_chain_ledger.py @@ -24,6 +24,7 @@ assemble_replay_and_verify, ) from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models import ( + ModelDeclaredChainHop, ModelDelegationTerminalPayload, ModelLedgerChainRow, ModelObservedHop, @@ -74,8 +75,76 @@ """ -def _load_contract_settings() -> tuple[tuple[str, ...], int, float]: - """Load the tier-2 authority and bounded settle policy from the contract.""" +def _parse_declared_topology( + topology_raw: object, +) -> tuple[ModelDeclaredChainHop, ...]: + """Turn the contract's ``chain_topology`` into declared hops, or refuse. + + OMN-18419. Every refusal here is a contract that cannot be graded against, + and a topology that cannot be graded against must fail LOUDLY at construction + rather than quietly produce a chain the replay rates on a relation it + invented. The four refusals are the four ways a parent relation can be + unresolvable: a hop named twice (which parent does an edge close against?), + a parent naming a topic that is not a declared hop, no head at all (every + hop caused by another is a cycle), and more than one head (two chains, not + one). + """ + if not isinstance(topology_raw, list) or not topology_raw: + raise RuntimeError("chain-writer contract must declare a non-empty topology") + + hops: list[ModelDeclaredChainHop] = [] + for entry in topology_raw: + if not isinstance(entry, Mapping): + raise RuntimeError( + "chain_topology entries must be mappings carrying `topic` and " + f"`parent`; got {entry!r}. The bare-topic list form cannot " + "express a branch, which is the OMN-18419 defect." + ) + try: + hops.append(ModelDeclaredChainHop.model_validate(dict(entry))) + except Exception as exc: + raise RuntimeError( + f"invalid chain_topology entry {entry!r}: {exc}" + ) from exc + + topics = [hop.topic for hop in hops] + duplicates = sorted({topic for topic in topics if topics.count(topic) > 1}) + if duplicates: + raise RuntimeError( + f"chain_topology declares {duplicates!r} more than once; a parent " + "relation resolved by topic cannot say which occurrence it means" + ) + + declared = set(topics) + dangling = sorted( + { + hop.parent + for hop in hops + if hop.parent is not None and hop.parent not in declared + } + ) + if dangling: + raise RuntimeError( + f"chain_topology names parent topic(s) {dangling!r} that are not " + "declared hops; an edge to an undeclared hop can never close" + ) + + heads = [hop.topic for hop in hops if hop.parent is None] + if not heads: + raise RuntimeError( + "chain_topology declares no head (every hop names a parent), which " + "is a cycle rather than a chain" + ) + if len(heads) > 1: + raise RuntimeError( + f"chain_topology declares {len(heads)} heads {heads!r}; one " + "correlation's chain has exactly one head" + ) + return tuple(hops) + + +def _load_contract_settings() -> tuple[tuple[ModelDeclaredChainHop, ...], int, float]: + """Load the declared topology and bounded settle policy from the contract.""" try: raw = yaml.safe_load( # yaml-safe-load-ok: trusted package contract _CONTRACT_PATH.read_text(encoding="utf-8") @@ -85,14 +154,7 @@ def _load_contract_settings() -> tuple[tuple[str, ...], int, float]: if not isinstance(raw, Mapping): raise RuntimeError("chain-writer contract root must be a mapping") - topology_raw = raw.get("chain_topology") - if ( - not isinstance(topology_raw, list) - or not topology_raw - or not all(isinstance(topic, str) and topic for topic in topology_raw) - ): - raise RuntimeError("chain-writer contract must declare a non-empty topology") - topology = tuple(str(topic) for topic in topology_raw) + topology = _parse_declared_topology(raw.get("chain_topology")) writer_raw = raw.get("writer") writer = writer_raw if isinstance(writer_raw, Mapping) else {} @@ -113,7 +175,7 @@ def __init__( container: ModelONEXContainer, db_dsn: str | None = None, *, - declared_chain: Sequence[str] | None = None, + declared_chain: Sequence[ModelDeclaredChainHop] | None = None, settle_attempts: int | None = None, settle_delay_seconds: float | None = None, ) -> None: @@ -186,10 +248,11 @@ async def handle( await self._ensure_db_ready() observed: tuple[ModelObservedHop, ...] = () + declared_topics = self._declared_topics() for attempt in range(self._settle_attempts): observed = await self._read_observed(correlation_id) observed_topics = {hop.topic for hop in observed} - if all(topic in observed_topics for topic in self._declared_chain): + if all(topic in observed_topics for topic in declared_topics): break if attempt + 1 < self._settle_attempts and self._settle_delay_seconds: await asyncio.sleep(self._settle_delay_seconds) @@ -207,7 +270,7 @@ async def handle( raise self._runtime_error( "no delegation-chain evidence to persist: public.event_ledger " f"carries no row for correlation {correlation_id} on any " - f"declared chain topic {list(self._declared_chain)!r} after " + f"declared chain topic {list(self._declared_topics())!r} after " f"{self._settle_attempts} settle attempt(s); no ledger_chain " "row can be written, and reporting success here would be " "indistinguishable from a complete write", @@ -222,6 +285,15 @@ async def handle( handler_id=HANDLER_ID_DELEGATION_CHAIN_LEDGER, ) + def _declared_topics(self) -> tuple[str, ...]: + """The declared hop topics, in declaration order. + + The read filter and the settle predicate want topics; the replay wants + the parent relation. Deriving the topic list here keeps the declaration + a single object rather than two lists free to disagree. + """ + return tuple(hop.topic for hop in self._declared_chain) + async def _read_observed( self, correlation_id: UUID ) -> tuple[ModelObservedHop, ...]: @@ -230,7 +302,7 @@ async def _read_observed( "operation": "db.query", "payload": { "sql": _SQL_READ_OBSERVED, - "parameters": [str(correlation_id), list(self._declared_chain)], + "parameters": [str(correlation_id), list(self._declared_topics())], }, "correlation_id": str(correlation_id), } diff --git a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/models/__init__.py b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/models/__init__.py index 9938f9af86..fca30732c3 100644 --- a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/models/__init__.py +++ b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/models/__init__.py @@ -6,6 +6,9 @@ from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.enum_tier_two_verdict import ( EnumTierTwoVerdict, ) +from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.model_declared_chain_hop import ( + ModelDeclaredChainHop, +) from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.model_delegation_terminal_payload import ( ModelDelegationTerminalPayload, ) @@ -18,6 +21,7 @@ __all__ = [ "EnumTierTwoVerdict", + "ModelDeclaredChainHop", "ModelDelegationTerminalPayload", "ModelLedgerChainRow", "ModelObservedHop", diff --git a/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/models/model_declared_chain_hop.py b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/models/model_declared_chain_hop.py new file mode 100644 index 0000000000..c5f6b62494 --- /dev/null +++ b/src/omnibase_infra/nodes/node_delegation_chain_ledger_effect/models/model_declared_chain_hop.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2025 OmniNode.ai Inc. +# SPDX-License-Identifier: MIT + +"""One hop of the chain the node contracts DECLARE must happen (OMN-18419). + +Why this model exists at all +---------------------------- +``chain_topology`` was an ordered list of topic strings. An ordered list can +say "these hops, in this order"; it cannot say "this hop was caused by that +one". The replay therefore had no declared parent to check against and +re-derived each hop's expected parent from whatever sat at ``index - 1``. + +That re-derivation is correct only for a LINE, and the delegation chain is a +TREE. Measured read-only on the .201 compose dev lane, correlation +``41235987-425c-481b-b2e3-8970083ce512`` (chain-canary run 35037024216): +``onex.evt.omnimarket.delegate-skill-completed.v1`` records its parent as the +``onex.cmd.omnimarket.delegate-skill.v1`` envelope, not as the routing +decision that preceded it in time — because the terminal is a consequence of +consuming the delegate-skill COMMAND, not of the routing decision. The +recorded edge was right and the re-derivation was wrong, so a correct chain +graded red. + +The fix is to make the declaration say what it means. Each hop names the +declared topic of the hop whose consumption caused it, and the replay grades +the recorded edge against THAT hop's observed envelope id. A branch is then +expressible, and nothing about this canary is special-cased: a line is simply +a tree in which every parent happens to be the preceding hop. + +``parent = None`` is the checkable statement "this hop is the chain HEAD", +the same claim an absent ``parent_message_id`` makes on the wire +(``envelope_header_identity``). It is a claim, not a gap: the replay refuses a +declared head that records a parent. +""" + +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict, Field, model_validator + + +class ModelDeclaredChainHop(BaseModel): + """A declared hop: the topic, and the declared topic that causes it.""" + + model_config = ConfigDict(frozen=True, extra="forbid") + + topic: str = Field( + min_length=1, + description="The topic this hop is declared to be observed on.", + ) + parent: str | None = Field( + default=None, + description=( + "The DECLARED TOPIC of the hop whose consumption causes this one. " + "None means this hop is declared to be the chain head, which the " + "replay checks rather than assumes: a declared head that records " + "a parent envelope is a replay failure, not a tolerated extra." + ), + ) + + @model_validator(mode="after") + def _refuse_self_causation(self) -> ModelDeclaredChainHop: + """A hop cannot declare itself as its own cause. + + The envelope model already refuses a self-edge on the wire + (``parent_envelope_id == envelope_id``). Refusing it in the + DECLARATION too means a contract can never ask the replay to check an + edge the transport would reject. + """ + if self.parent is not None and self.parent == self.topic: + raise ValueError( + f"declared hop {self.topic!r} names itself as its own parent; " + "a self-causing hop is not a chain" + ) + return self + + +__all__ = ["ModelDeclaredChainHop"] diff --git a/src/omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml b/src/omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml index 64f956a2ac..a82d8bd873 100644 --- a/src/omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +++ b/src/omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml @@ -45,20 +45,28 @@ # topic COUNT in the prose above, which still said 26 after OMN-18013 # deleted six category-less DLQ subscriptions and left 20 in the list. # The list is the authority; the count now matches it at 24. +# - OMN-18419: widen subscribe_topics from 24 to 25 by adding the FIFTH +# delegation-chain hop, onex.cmd.omnibase-infra.delegation-request.v1 -- +# the pattern-B worker command the runtime's delegation dispatch port +# publishes while consuming the delegate-skill command. It was on the wire +# and not in the ledger, so the routing request's recorded parent named an +# envelope no correlation-scoped read could resolve and chain-canary link 5 +# graded a correct edge red. Paired subscribe_topics+handler_routing diff, +# same OMN-14594 pattern. # Contract identifiers name: "node_ledger_projection_compute" contract_name: "node_ledger_projection_compute" node_name: "node_ledger_projection_compute" contract_version: major: 1 - minor: 3 + minor: 4 patch: 0 -node_version: "0.4.0" +node_version: "0.5.0" # Node type - COMPUTE for event projection logic node_type: "COMPUTE_GENERIC" # Description description: > - COMPUTE node that subscribes to 24 topics (7 platform-lifecycle + 12 business command/completion/DLQ topics remaining from OMN-15006 after OMN-18013 deleted six category-less DLQ subscriptions + 1 external steel_onslaught terminal-event topic, OMN-15168 + 4 delegation-chain topics, OMN-18398) for event ledger persistence. Projects events from the platform event bus into the audit ledger, enabling complete traceability and debugging support. Uses consumer_purpose="audit" to indicate non-processing read-only consumption and auto_offset_reset="earliest" to capture all historical events. Contract 1.3.0 (OMN-18398) adds the four delegation-chain topics the chain-canary link-5 writer reads back out of public.event_ledger; contract 1.2.0 (OMN-15168) adds the steel_onslaught terminal-match topic as a paired subscribe_topics+handler_routing diff; contract 1.1.0 (OMN-15006) widened the truth surface to build_loop + OCC governance + DLQ topics whose silent loss OMN-15002 documented; contract patch 2 (1.0.2) recorded the OMN-14823 canonical def-B handler entrypoint flip. + COMPUTE node that subscribes to 25 topics (7 platform-lifecycle + 12 business command/completion/DLQ topics remaining from OMN-15006 after OMN-18013 deleted six category-less DLQ subscriptions + 1 external steel_onslaught terminal-event topic, OMN-15168 + 5 delegation-chain topics, OMN-18398 and OMN-18419) for event ledger persistence. Projects events from the platform event bus into the audit ledger, enabling complete traceability and debugging support. Uses consumer_purpose="audit" to indicate non-processing read-only consumption and auto_offset_reset="earliest" to capture all historical events. Contract 1.4.0 (OMN-18419) adds the fifth delegation-chain hop, delegation-request.v1, without which the routing request's recorded causal parent resolved to nothing; contract 1.3.0 (OMN-18398) adds the four delegation-chain topics the chain-canary link-5 writer reads back out of public.event_ledger; contract 1.2.0 (OMN-15168) adds the steel_onslaught terminal-match topic as a paired subscribe_topics+handler_routing diff; contract 1.1.0 (OMN-15006) widened the truth surface to build_loop + OCC governance + DLQ topics whose silent loss OMN-15002 documented; contract patch 2 (1.0.2) recorded the OMN-14823 canonical def-B handler entrypoint flip. # Event bus configuration event_bus: @@ -66,11 +74,12 @@ event_bus: major: 1 minor: 0 patch: 0 - # Subscribe to 24 topics for complete audit coverage: 7 platform-lifecycle + # Subscribe to 25 topics for complete audit coverage: 7 platform-lifecycle # topics, plus the 12 business command/completion/DLQ topics that remain from # OMN-15006 after OMN-18013 deleted six category-less DLQ subscriptions, plus 1 # external steel_onslaught terminal-event topic (OMN-15168), plus the 4 - # delegation-chain topics (OMN-18398). Counted from the list below, which is + # delegation-chain topics (OMN-18398) plus the fifth (OMN-18419). Counted + # from the list below, which is # the only authority -- the prose said 26 for as long as the list said 20. subscribe_topics: # Node lifecycle events @@ -138,6 +147,14 @@ event_bus: - "onex.cmd.omnibase-infra.delegation-routing-request.v1" - "onex.evt.omnibase-infra.routing-decision.v1" - "onex.evt.omnimarket.delegate-skill-completed.v1" + # --- OMN-18419: the fifth delegation-chain hop --- + # The pattern-B worker command the runtime's delegation dispatch port + # publishes while consuming the delegate-skill command. It was always on + # the wire and never projected, so the routing request's recorded parent + # pointed at an envelope no chain read could resolve and the edge could + # not close. node_delegation_chain_ledger_effect's contract 1.1.0 declares + # it as a hop with delegate-skill as its parent. + - "onex.cmd.omnibase-infra.delegation-request.v1" # Audit consumer - read-only, non-processing consumption for ledger persistence consumer_purpose: "audit" # Start from earliest offset to capture all historical events @@ -149,7 +166,7 @@ input_model: name: "ModelEventMessage" module: "omnibase_infra.event_bus.models.model_event_message" description: > - Kafka event message containing raw bytes payload and headers. The compute node processes events from all 26 subscribed topics. + Kafka event message containing raw bytes payload and headers. The compute node processes events from all 25 subscribed topics. output_model: name: "ModelIntent" @@ -486,6 +503,20 @@ handler_routing: module: "omnibase_infra.nodes.node_ledger_projection_compute.handlers.handler_ledger_projection" supported_operations: - "ledger.project" + # OMN-18419: the fifth chain hop, paired with its subscribe_topics entry + # above per the OMN-14594 rule. + - topic: "onex.cmd.omnibase-infra.delegation-request.v1" + operation: ledger.project + message_category: "command" + handler_type: "ledger_projection" + event_model: + name: "ModelEventMessage" + module: "omnibase_infra.event_bus.models.model_event_message" + handler: + name: "HandlerLedgerProjection" + module: "omnibase_infra.nodes.node_ledger_projection_compute.handlers.handler_ledger_projection" + supported_operations: + - "ledger.project" - topic: "onex.evt.omnimarket.delegate-skill-completed.v1" operation: ledger.project message_category: "event" diff --git a/src/omnibase_infra/runtime/auto_wiring/handler_wiring.py b/src/omnibase_infra/runtime/auto_wiring/handler_wiring.py index eece5256e9..357d491f1f 100644 --- a/src/omnibase_infra/runtime/auto_wiring/handler_wiring.py +++ b/src/omnibase_infra/runtime/auto_wiring/handler_wiring.py @@ -4910,6 +4910,44 @@ def _extract_state_io_metadata(payload_json: str) -> StateIoMetadata: ) +def _consumed_envelope_id(envelope: object) -> UUID | None: + """The identity of the envelope this dispatch consumed, or None. + + OMN-18419. ``MessageDispatchEngine`` hands a dispatcher the JSON-safe + MATERIALIZATION of the envelope (``_materialize_envelope_with_bindings``), + not the typed envelope, and binds the typed one beside it on a contextvar + for exactly this reason -- its own comment says "for transport identity + (for example envelope_id)". The stateful wrapper read ``envelope_id`` as an + ATTRIBUTE off that dict, which is always ``None``, so every outbox entry + recorded the CORRELATION id as its causation via the fallback below. + + Measured on the .201 compose dev lane, correlation + ``41235987-425c-481b-b2e3-8970083ce512``: the routing intent's deterministic + id re-derives exactly as ``uuid5(correlation, f"{correlation}:ModelRoutingIntent:0")`` + -- the self-seeded fallback -- and not from the + ``onex.cmd.omnibase-infra.delegation-request.v1`` envelope + ``f1cc9a51-ef02-40f4-b2e7-81e5b57942ed`` that actually caused it. + + The contextvar is consulted FIRST and the attribute second, so a caller + that hands this wrapper a real envelope directly (tests, the no-bus path) + keeps working unchanged. + """ + typed = current_dispatch_envelope() + if typed is not None: + typed_id = getattr(typed, "envelope_id", None) + if isinstance(typed_id, UUID): + return typed_id + direct = getattr(envelope, "envelope_id", None) + if isinstance(direct, UUID): + return direct + if isinstance(direct, str) and direct: + try: + return UUID(direct) + except ValueError: + return None + return None + + def _make_stateful_dispatch_callback( handler_instance: ProtocolHandleable, event_model: ModelHandlerRef | None, @@ -5268,11 +5306,32 @@ async def _publish_outbox_batch(entries: list[dict[str, object]]) -> int: # derives ``None`` (the field default), so this is safe for every # topic shape the outbox can resolve. event_type = derive_event_type_from_topic(topic) + # OMN-18419: the causal edge, recorded rather than discarded. + # + # `causation` is the envelope whose consumption produced this + # emission. It was already in hand here -- it seeds the + # deterministic id one line above -- and was not put on the + # envelope, so every event published off this path arrived in + # `event_ledger` with a null `parent_message_id`: the checkable + # statement "chain head", asserted by hops that are not heads. + # `publish_envelope` binds the wire header from the envelope + # (`header_identity_fields_from_envelope`), so setting it here is + # what puts it on the wire. + # + # The ONE case that is deliberately NOT an edge is the + # completion-bound sweep, which seeds `causation_envelope_id` with + # the row's own correlation id precisely because no causing + # envelope exists (see `_terminalise_abandoned_rows`). A + # correlation id is not an envelope id, so recording it would + # fabricate an edge that can never close. Absence is the honest + # encoding of absence, the same rule `chain_replay` holds. + edge = None if causation == cid_uuid else causation out_envelope: _Envelope[BaseModel] = _Envelope( envelope_id=envelope_id, payload=payload, correlation_id=cid_uuid, event_type=event_type, + parent_envelope_id=edge, ) key: bytes | None = None for attr in ("entity_id", "node_id", "session_id", "correlation_id"): @@ -5613,7 +5672,7 @@ async def _load_handle_persist( # preserved. The resume predicate keys on envelope_id, NOT causation_id # (spec §4.1 E1 — a redelivered input keeps its envelope_id; its own # causation_id is the grandparent and would never match). - incoming_envelope_id = getattr(envelope, "envelope_id", None) + incoming_envelope_id = _consumed_envelope_id(envelope) locked = await _find_recoverable_row(cid) if locked is not None: entries = list( diff --git a/src/omnibase_infra/runtime/service_pattern_b_broker.py b/src/omnibase_infra/runtime/service_pattern_b_broker.py index 8fe080deb4..98537f0022 100644 --- a/src/omnibase_infra/runtime/service_pattern_b_broker.py +++ b/src/omnibase_infra/runtime/service_pattern_b_broker.py @@ -34,6 +34,9 @@ ProtocolPatternBBrokerTransport, ) from omnibase_infra.runtime.contract_terminal_events import resolve_terminal_verdict +from omnibase_infra.runtime.dispatch_envelope_context import ( + current_dispatch_envelope, +) from omnibase_infra.runtime.runtime_local_ingress import ModelRuntimeLocalIngressRoute from omnibase_infra.utils.util_error_sanitization import ( sanitize_error_message, @@ -806,6 +809,29 @@ async def _publish_worker_command( command: ModelDispatchBusCommand, route: ModelRuntimeLocalIngressRoute, ) -> None: + """Publish the route's worker command, recording what caused it. + + OMN-18419. This method publishes TWO different hops of the delegation + chain, and until now both were published as chain heads. + + * From the HTTP ingress there is no consumed envelope, so the worker + command genuinely IS the head. `current_dispatch_envelope()` is None + and nothing is recorded -- an absent `parent_message_id` is the + checkable statement "head", and inventing one here would make that + statement unfalsifiable. + * From `service_delegation_dispatch_port`, this runs INSIDE the + delegate-skill handler's dispatch, which the dispatch engine bound to + the `onex.cmd.omnimarket.delegate-skill.v1` envelope it consumed. + That envelope is the cause of this command, and dropping it is why + `onex.cmd.omnibase-infra.delegation-routing-request.v1` -- published + two hops later off this one -- had no resolvable ancestry in + `event_ledger`. + + Same contextvar, same reason, as the OMN-18116 causal-edge origination + site in `DispatchResultApplier`: the canonical handler signature never + sees an envelope, so origination belongs in the runtime. + """ + consumed = current_dispatch_envelope() worker_envelope = ModelEventEnvelope[object]( payload=command.payload, correlation_id=command.correlation_id, @@ -813,6 +839,7 @@ async def _publish_worker_command( event_type=route.event_type, source_tool="pattern-b-broker", target_tool=route.contract_name, + parent_envelope_id=(None if consumed is None else consumed.envelope_id), ) await self._event_bus.publish( route.command_topic, diff --git a/tests/fixtures/dispatch_parity/baseline-selection-v2.json b/tests/fixtures/dispatch_parity/baseline-selection-v2.json index 5a92d48de8..d0ca59ff8a 100644 --- a/tests/fixtures/dispatch_parity/baseline-selection-v2.json +++ b/tests/fixtures/dispatch_parity/baseline-selection-v2.json @@ -709,6 +709,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -722,6 +723,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -771,6 +773,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -784,6 +787,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -833,6 +837,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -846,6 +851,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -895,6 +901,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -908,6 +915,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -957,6 +965,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -970,6 +979,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1019,6 +1029,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1032,6 +1043,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1081,6 +1093,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1094,6 +1107,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1143,6 +1157,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1156,6 +1171,71 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", + "onex.cmd.omnibase-infra.delegation-routing-request.v1", + "onex.cmd.omnimarket.delegate-skill.v1", + "onex.cmd.omnimarket.redeploy-start.v1", + "onex.cmd.platform.request-introspection.v1", + "onex.dlq.omnibase-infra.commands.v1", + "onex.dlq.omnibase-infra.events.v1", + "onex.dlq.omnibase-infra.intents.v1", + "onex.evt.occ.nightly-promotion.v1", + "onex.evt.omnibase-infra.build-loop-appended.v1", + "onex.evt.omnibase-infra.routing-decision.v1", + "onex.evt.omnimarket.build-loop-orchestrator-completed.v1", + "onex.evt.omnimarket.delegate-skill-completed.v1", + "onex.evt.omnimarket.runtime-deployment-proof.v1", + "onex.evt.onex-change-control.contract-drift-detected.v1", + "onex.evt.onex-change-control.cosmetic-compliance-scored.v1", + "onex.evt.onex-change-control.governance-check-completed.v1", + "onex.evt.platform.fsm-state-transitions.v1", + "onex.evt.platform.node-heartbeat.v1", + "onex.evt.platform.node-introspection.v1", + "onex.evt.platform.node-registration.v1", + "onex.evt.platform.registration-snapshots.v1", + "onex.evt.steel-onslaught.match-terminal.v1", + "onex.intent.platform.runtime-tick.v1", + "platform.fsm-state-transitions", + "platform.node-heartbeat", + "platform.node-introspection", + "platform.node-registration", + "platform.registration-snapshots", + "platform.request-introspection", + "platform.runtime-tick", + "steel-onslaught.match-terminal" + ], + "package": "omnibase_infra", + "type_scoped": true + }, + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214": { + "category": "command", + "contract_name": "node_ledger_projection_compute", + "event_model_module": "omnibase_infra.event_bus.models.model_event_message", + "event_model_name": "ModelEventMessage", + "handler_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "handler_module": "omnibase_infra.nodes.node_ledger_projection_compute.handlers.handler_ledger_projection", + "handler_name": "HandlerLedgerProjection", + "message_types": [ + "ModelEventMessage", + "occ.nightly-promotion", + "omnibase-infra.build-loop-append", + "omnibase-infra.build-loop-appended", + "omnibase-infra.commands", + "omnibase-infra.delegation-request", + "omnibase-infra.delegation-routing-request", + "omnibase-infra.events", + "omnibase-infra.intents", + "omnibase-infra.routing-decision", + "omnimarket.build-loop-orchestrator-completed", + "omnimarket.delegate-skill", + "omnimarket.delegate-skill-completed", + "omnimarket.redeploy-start", + "omnimarket.runtime-deployment-proof", + "onex-change-control.contract-drift-detected", + "onex-change-control.cosmetic-compliance-scored", + "onex-change-control.governance-check-completed", + "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1205,6 +1285,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1218,6 +1299,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1267,6 +1349,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1280,6 +1363,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1329,6 +1413,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1342,6 +1427,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1391,6 +1477,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1404,6 +1491,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1453,6 +1541,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1466,6 +1555,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1515,6 +1605,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1528,6 +1619,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1577,6 +1669,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1590,6 +1683,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1639,6 +1733,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1652,6 +1747,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1701,6 +1797,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1714,6 +1811,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1763,6 +1861,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1776,6 +1875,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1825,6 +1925,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1838,6 +1939,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1887,6 +1989,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1900,6 +2003,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -1949,6 +2053,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -1962,6 +2067,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -2011,6 +2117,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -2024,6 +2131,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -2073,6 +2181,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -2086,6 +2195,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -2135,6 +2245,7 @@ "omnibase-infra.build-loop-append", "omnibase-infra.build-loop-appended", "omnibase-infra.commands", + "omnibase-infra.delegation-request", "omnibase-infra.delegation-routing-request", "omnibase-infra.events", "omnibase-infra.intents", @@ -2148,6 +2259,7 @@ "onex-change-control.cosmetic-compliance-scored", "onex-change-control.governance-check-completed", "onex.cmd.omnibase-infra.build-loop-append.v1", + "onex.cmd.omnibase-infra.delegation-request.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnimarket.redeploy-start.v1", @@ -3172,11 +3284,11 @@ }, "contracts_discovered": 144, "discovery_errors": 0, - "distinct_subscribe_topics": 101, - "probe_count": 923, - "registered_dispatchers": 122, - "registered_routes": 117, - "type_scoped_dispatchers": 70 + "distinct_subscribe_topics": 102, + "probe_count": 974, + "registered_dispatchers": 123, + "registered_routes": 118, + "type_scoped_dispatchers": 71 }, "duplicate_winners": [], "epic": "OMN-12525", @@ -3216,7 +3328,7 @@ "omnimemory" ], "fixture_version": "v2", - "generated_at_utc": "2026-09-16T00:55:01.520361+00:00", + "generated_at_utc": "2026-09-16T02:12:49.422930+00:00", "installed_package_versions": { "omnibase-core": "0.47.14", "omnibase-infra": "0.38.29", @@ -3400,6 +3512,21 @@ }, "topic": "onex.cmd.omnibase-infra.coding-agent-workspace-validate.v1" }, + "P1a::onex.cmd.omnibase-infra.delegation-request.v1": { + "family": "P1_topic_event_type_matrix", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "_DictPayload" + }, + "selection": { + "dispatcher_ids": [], + "dlq_topic": "onex.dlq.omnibase-infra.omnibase-infra.v1", + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "no_dispatcher" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P1a::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "family": "P1_topic_event_type_matrix", "input": { @@ -4983,6 +5110,21 @@ }, "topic": "onex.cmd.omnibase-infra.coding-agent-workspace-validate.v1" }, + "P1b::onex.cmd.omnibase-infra.delegation-request.v1": { + "family": "P1_topic_event_type_matrix", + "input": { + "event_type": null, + "payload": "_DictPayload" + }, + "selection": { + "dispatcher_ids": [], + "dlq_topic": "onex.dlq.omnibase-infra.commands.v1", + "message_category": "command", + "message_type": "_DictPayload", + "status": "no_dispatcher" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P1b::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "family": "P1_topic_event_type_matrix", "input": { @@ -6979,6 +7121,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_09114b86::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_09114b86", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_09114b86::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_09114b86", @@ -7462,6 +7624,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_106cf59a::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_106cf59a", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_106cf59a::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_106cf59a", @@ -7945,6 +8127,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_20b031bf::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_20b031bf", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_20b031bf::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_20b031bf", @@ -8428,6 +8630,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3579d375::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3579d375", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3579d375::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3579d375", @@ -8911,6 +9133,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3bd91ec3::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3bd91ec3", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3bd91ec3::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3bd91ec3", @@ -9394,6 +9636,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_4180e0d9::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_4180e0d9", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_4180e0d9::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_4180e0d9", @@ -9877,6 +10139,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_520a72c1::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_520a72c1", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_520a72c1::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_520a72c1", @@ -10360,6 +10642,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", @@ -10704,7 +11006,510 @@ }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.platform.node-heartbeat.v1": { "construct_only": true, - "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "platform.node-heartbeat", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e1f3db33" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "platform.node-heartbeat", + "status": "success" + }, + "topic": "onex.evt.platform.node-heartbeat.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.platform.node-introspection.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "platform.node-introspection", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_4180e0d9" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "platform.node-introspection", + "status": "success" + }, + "topic": "onex.evt.platform.node-introspection.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.platform.node-registration.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "platform.node-registration", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_d9e78fa2" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "platform.node-registration", + "status": "success" + }, + "topic": "onex.evt.platform.node-registration.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.platform.registration-snapshots.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "platform.registration-snapshots", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_cb26001f" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "platform.registration-snapshots", + "status": "success" + }, + "topic": "onex.evt.platform.registration-snapshots.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.steel-onslaught.match-terminal.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "steel-onslaught.match-terminal", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_dfa36ec6" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "steel-onslaught.match-terminal", + "status": "success" + }, + "topic": "onex.evt.steel-onslaught.match-terminal.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.intent.platform.runtime-tick.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "platform.runtime-tick", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_982021ab" + ], + "dlq_topic": null, + "message_category": "intent", + "message_type": "platform.runtime-tick", + "status": "success" + }, + "topic": "onex.intent.platform.runtime-tick.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.cmd.omnibase-infra.build-loop-append.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.build-loop-append", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_build_loop_write_effect.HandlerBuildLoopAppend.build_loop_append_1eb0a5fb", + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_b1cf841e" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.build-loop-append", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.cmd.omnibase-infra.delegation-routing-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-routing-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e28bbe9e" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-routing-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-routing-request.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.cmd.omnimarket.delegate-skill.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnimarket.delegate-skill", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5a09f3c2" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnimarket.delegate-skill", + "status": "success" + }, + "topic": "onex.cmd.omnimarket.delegate-skill.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.cmd.omnimarket.redeploy-start.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnimarket.redeploy-start", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_8d5b772c" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnimarket.redeploy-start", + "status": "success" + }, + "topic": "onex.cmd.omnimarket.redeploy-start.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.cmd.platform.request-introspection.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "platform.request-introspection", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "platform.request-introspection", + "status": "success" + }, + "topic": "onex.cmd.platform.request-introspection.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.dlq.omnibase-infra.commands.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.commands", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_09114b86" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.commands", + "status": "success" + }, + "topic": "onex.dlq.omnibase-infra.commands.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.dlq.omnibase-infra.events.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.events", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_dlq_replay_effect.HandlerDlqReplay.replay_dlq_8a4ba739", + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a132611f" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "omnibase-infra.events", + "status": "success" + }, + "topic": "onex.dlq.omnibase-infra.events.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.dlq.omnibase-infra.intents.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.intents", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_520a72c1" + ], + "dlq_topic": null, + "message_category": "intent", + "message_type": "omnibase-infra.intents", + "status": "success" + }, + "topic": "onex.dlq.omnibase-infra.intents.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.occ.nightly-promotion.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "occ.nightly-promotion", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a0d95493" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "occ.nightly-promotion", + "status": "success" + }, + "topic": "onex.evt.occ.nightly-promotion.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.omnibase-infra.build-loop-appended.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.build-loop-appended", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3579d375" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "omnibase-infra.build-loop-appended", + "status": "success" + }, + "topic": "onex.evt.omnibase-infra.build-loop-appended.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.omnibase-infra.routing-decision.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.routing-decision", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_94163f65" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "omnibase-infra.routing-decision", + "status": "success" + }, + "topic": "onex.evt.omnibase-infra.routing-decision.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.omnimarket.build-loop-orchestrator-completed.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnimarket.build-loop-orchestrator-completed", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_build_loop_projection_compute.HandlerBuildLoopProjection.build_loop_project_b48dcfa8", + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_6ef6ade1" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "omnimarket.build-loop-orchestrator-completed", + "status": "success" + }, + "topic": "onex.evt.omnimarket.build-loop-orchestrator-completed.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.omnimarket.delegate-skill-completed.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnimarket.delegate-skill-completed", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_c2df17da" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "omnimarket.delegate-skill-completed", + "status": "success" + }, + "topic": "onex.evt.omnimarket.delegate-skill-completed.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.omnimarket.runtime-deployment-proof.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnimarket.runtime-deployment-proof", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_ba940a93" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "omnimarket.runtime-deployment-proof", + "status": "success" + }, + "topic": "onex.evt.omnimarket.runtime-deployment-proof.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.onex-change-control.contract-drift-detected.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "onex-change-control.contract-drift-detected", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_85d7b3d6" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "onex-change-control.contract-drift-detected", + "status": "success" + }, + "topic": "onex.evt.onex-change-control.contract-drift-detected.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.onex-change-control.cosmetic-compliance-scored.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "onex-change-control.cosmetic-compliance-scored", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_20b031bf" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "onex-change-control.cosmetic-compliance-scored", + "status": "success" + }, + "topic": "onex.evt.onex-change-control.cosmetic-compliance-scored.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.onex-change-control.governance-check-completed.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "onex-change-control.governance-check-completed", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_106cf59a" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "onex-change-control.governance-check-completed", + "status": "success" + }, + "topic": "onex.evt.onex-change-control.governance-check-completed.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.platform.fsm-state-transitions.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "platform.fsm-state-transitions", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_3bd91ec3" + ], + "dlq_topic": null, + "message_category": "event", + "message_type": "platform.fsm-state-transitions", + "status": "success" + }, + "topic": "onex.evt.platform.fsm-state-transitions.v1" + }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.platform.node-heartbeat.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", "family": "P4_payload_type_scoping", "input": { @@ -10722,9 +11527,9 @@ }, "topic": "onex.evt.platform.node-heartbeat.v1" }, - "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.platform.node-introspection.v1": { + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.platform.node-introspection.v1": { "construct_only": true, - "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", "family": "P4_payload_type_scoping", "input": { @@ -10742,9 +11547,9 @@ }, "topic": "onex.evt.platform.node-introspection.v1" }, - "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.platform.node-registration.v1": { + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.platform.node-registration.v1": { "construct_only": true, - "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", "family": "P4_payload_type_scoping", "input": { @@ -10762,9 +11567,9 @@ }, "topic": "onex.evt.platform.node-registration.v1" }, - "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.platform.registration-snapshots.v1": { + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.platform.registration-snapshots.v1": { "construct_only": true, - "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", "family": "P4_payload_type_scoping", "input": { @@ -10782,9 +11587,9 @@ }, "topic": "onex.evt.platform.registration-snapshots.v1" }, - "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.evt.steel-onslaught.match-terminal.v1": { + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.evt.steel-onslaught.match-terminal.v1": { "construct_only": true, - "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", "family": "P4_payload_type_scoping", "input": { @@ -10802,9 +11607,9 @@ }, "topic": "onex.evt.steel-onslaught.match-terminal.v1" }, - "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7::onex.intent.platform.runtime-tick.v1": { + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214::onex.intent.platform.runtime-tick.v1": { "construct_only": true, - "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_58404bf7", + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", "family": "P4_payload_type_scoping", "input": { @@ -10843,6 +11648,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5a09f3c2::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5a09f3c2", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5a09f3c2::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5a09f3c2", @@ -11326,6 +12151,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_6ef6ade1::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_6ef6ade1", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_6ef6ade1::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_6ef6ade1", @@ -11809,6 +12654,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_85d7b3d6::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_85d7b3d6", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_85d7b3d6::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_85d7b3d6", @@ -12292,6 +13157,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_8d5b772c::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_8d5b772c", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_8d5b772c::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_8d5b772c", @@ -12775,6 +13660,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_94163f65::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_94163f65", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_94163f65::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_94163f65", @@ -13258,6 +14163,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_982021ab::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_982021ab", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_982021ab::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_982021ab", @@ -13741,6 +14666,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a0d95493::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a0d95493", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a0d95493::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a0d95493", @@ -14224,6 +15169,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a132611f::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a132611f", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a132611f::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_a132611f", @@ -14707,6 +15672,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_b1cf841e::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_b1cf841e", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_b1cf841e::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_b1cf841e", @@ -15190,6 +16175,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_ba940a93::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_ba940a93", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_ba940a93::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_ba940a93", @@ -15673,6 +16678,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_c2df17da::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_c2df17da", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_c2df17da::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_c2df17da", @@ -16156,6 +17181,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_cb26001f::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_cb26001f", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_cb26001f::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_cb26001f", @@ -16639,6 +17684,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_d9e78fa2::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_d9e78fa2", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_d9e78fa2::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_d9e78fa2", @@ -17122,6 +18187,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_dfa36ec6::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_dfa36ec6", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_dfa36ec6::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_dfa36ec6", @@ -17605,6 +18690,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e1f3db33::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e1f3db33", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e1f3db33::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e1f3db33", @@ -18088,6 +19193,26 @@ }, "topic": "onex.cmd.omnibase-infra.build-loop-append.v1" }, + "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e28bbe9e::onex.cmd.omnibase-infra.delegation-request.v1": { + "construct_only": true, + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e28bbe9e", + "event_model": "omnibase_infra.event_bus.models.model_event_message.ModelEventMessage", + "family": "P4_payload_type_scoping", + "input": { + "event_type": "omnibase-infra.delegation-request", + "payload": "ModelEventMessage" + }, + "selection": { + "dispatcher_ids": [ + "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214" + ], + "dlq_topic": null, + "message_category": "command", + "message_type": "omnibase-infra.delegation-request", + "status": "success" + }, + "topic": "onex.cmd.omnibase-infra.delegation-request.v1" + }, "P4::dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e28bbe9e::onex.cmd.omnibase-infra.delegation-routing-request.v1": { "construct_only": true, "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_e28bbe9e", @@ -21146,6 +22271,16 @@ "topic_pattern": "*.cmd.platform.request-introspection.*", "type_scoped": true }, + { + "contract_name": "node_ledger_projection_compute", + "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "handler_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214", + "message_category": "command", + "route_id": "route.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5901b214.onex_cmd_omnibase_infra_delegation_request_v1", + "topic": "onex.cmd.omnibase-infra.delegation-request.v1", + "topic_pattern": "*.cmd.omnibase-infra.delegation-request.*", + "type_scoped": true + }, { "contract_name": "node_ledger_projection_compute", "dispatcher_id": "dispatcher.auto.node_ledger_projection_compute.HandlerLedgerProjection.ledger_project_5a09f3c2", diff --git a/tests/integration/nodes/node_delegation_chain_ledger_effect/test_absent_evidence_refuses_integration.py b/tests/integration/nodes/node_delegation_chain_ledger_effect/test_absent_evidence_refuses_integration.py index dedab14a8f..afe6a93502 100644 --- a/tests/integration/nodes/node_delegation_chain_ledger_effect/test_absent_evidence_refuses_integration.py +++ b/tests/integration/nodes/node_delegation_chain_ledger_effect/test_absent_evidence_refuses_integration.py @@ -35,6 +35,7 @@ HandlerDelegationChainLedger, ) from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models import ( + ModelDeclaredChainHop, ModelObservedHop, ) from omnibase_infra.runtime.auto_wiring.handler_wiring import wire_from_manifest @@ -50,16 +51,28 @@ from omnibase_infra.runtime.message_dispatch_engine import MessageDispatchEngine _SUBSCRIBE_TOPIC = "onex.evt.omnimarket.delegate-skill-completed.v1" -_CHAIN = ( +_CHAIN_TOPICS = ( "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.evt.omnibase-infra.routing-decision.v1", _SUBSCRIBE_TOPIC, ) +# OMN-18419: the declaration carries a parent relation per hop, not bare +# topics. This harness declares a LINE, which is what `_observed` builds; the +# TREE cases live in tests/unit/.../test_chain_replay.py beside the grading +# rule. What this file exercises is the refusal path through the real wiring, +# which is indifferent to the topology's shape. +_CHAIN = tuple( + ModelDeclaredChainHop( + topic=topic, + parent=None if index == 0 else _CHAIN_TOPICS[index - 1], + ) + for index, topic in enumerate(_CHAIN_TOPICS) +) def _observed(correlation_id: UUID) -> tuple[ModelObservedHop, ...]: - envelope_ids = tuple(uuid4() for _ in _CHAIN) + envelope_ids = tuple(uuid4() for _ in _CHAIN_TOPICS) return tuple( ModelObservedHop( topic=topic, @@ -67,7 +80,7 @@ def _observed(correlation_id: UUID) -> tuple[ModelObservedHop, ...]: parent_envelope_id=None if index == 0 else envelope_ids[index - 1], correlation_id=correlation_id, ) - for index, topic in enumerate(_CHAIN) + for index, topic in enumerate(_CHAIN_TOPICS) ) @@ -224,7 +237,7 @@ async def test_absent_evidence_never_completes_silently( if "no delegation-chain evidence to persist" in message ] assert refusals, "the engine recorded no typed refusal naming absent evidence" - for topic in _CHAIN: + for topic in _CHAIN_TOPICS: assert any(topic in message for message in refusals), ( f"the refusal does not name {topic!r}, so it does not say what " "evidence was looked for" @@ -251,7 +264,7 @@ async def test_present_evidence_persists_and_takes_no_error_route( handler._read_observed.assert_awaited() # type: ignore[attr-defined] persist_rows = handler._persist_rows # type: ignore[attr-defined] persist_rows.assert_awaited_once() - assert len(persist_rows.await_args.args[0]) == len(_CHAIN) + assert len(persist_rows.await_args.args[0]) == len(_CHAIN_TOPICS) for logger in _ERROR_LOGGERS: assert not _errors(caplog, logger), ( f"{logger} recorded an error on the success path: " diff --git a/tests/integration/runtime/test_chain_causal_edge_seam_omn18419.py b/tests/integration/runtime/test_chain_causal_edge_seam_omn18419.py new file mode 100644 index 0000000000..f5fec31ccd --- /dev/null +++ b/tests/integration/runtime/test_chain_causal_edge_seam_omn18419.py @@ -0,0 +1,295 @@ +# SPDX-FileCopyrightText: 2025 OmniNode.ai Inc. +# SPDX-License-Identifier: MIT +"""The two publish seams that dropped the delegation chain's causal edge (OMN-18419). + +What was measured +----------------- +Read-only on the .201 compose dev lane, ``public.event_ledger`` for the +chain-canary correlation ``41235987-425c-481b-b2e3-8970083ce512`` (run +35037024216):: + + onex.cmd.omnimarket.delegate-skill.v1 6c9dc22f-… parent= + onex.cmd.omnibase-infra.delegation-routing-request.v1 841f9c10-… parent= + onex.evt.omnibase-infra.routing-decision.v1 223b9623-… parent=841f9c10-… + onex.evt.omnimarket.delegate-skill-completed.v1 3b1b8925-… parent=6c9dc22f-… + +The routing request published NO causal edge at all, and an absent +``parent_message_id`` is the checkable statement "this hop is a chain HEAD", +which it is not. Two runtime seams produced that null, and this file drives +both. + +Seam 1 — the pattern-B worker command +------------------------------------- +``RuntimePatternBBroker._publish_worker_command`` builds a fresh envelope for +the route's command topic. It publishes TWO hops of this chain: the head, from +the HTTP ingress, and ``onex.cmd.omnibase-infra.delegation-request.v1``, from +``service_delegation_dispatch_port`` — which runs INSIDE the delegate-skill +handler's dispatch. Both were published as heads. The second is not one, and +that missing edge is why every hop downstream of it pointed at an envelope no +correlation-scoped read could resolve. + +Seam 2 — the state_io in-row outbox +----------------------------------- +``MessageDispatchEngine`` hands a dispatcher the JSON-safe MATERIALIZATION of +the envelope and binds the typed envelope beside it on a contextvar, saying so +in its own comment: "for transport identity (for example envelope_id)". The +stateful wrapper read ``envelope_id`` as an ATTRIBUTE off that mapping, which +is always ``None``, so every outbox entry fell back to seeding its causation +with the CORRELATION id. That is provable from the wire: the routing intent's +deterministic id on the run above re-derives exactly as +``uuid5(correlation, f"{correlation}:ModelRoutingIntent:0")`` and NOT from the +``delegation-request`` envelope ``f1cc9a51-ef02-40f4-b2e7-81e5b57942ed`` that +caused it. ``_publish_outbox_batch`` then dropped even that seed from the +published envelope. + +Why these tests are shaped this way +----------------------------------- +Each drives the REAL seam — a live broker across a real subscribe/publish +boundary, and the real dispatch engine invoking a real registered dispatcher — +rather than calling the changed function with a hand-built argument. Each +carries a positive control that would catch a broken fixture: the correlation +id still arrives, and the materialized payload really is the attribute-less +mapping that caused the fallback. +""" + +from __future__ import annotations + +import asyncio +from collections.abc import Mapping +from datetime import UTC, datetime +from uuid import UUID, uuid4 + +import pytest + +from omnibase_core.models.dispatch.model_dispatch_bus_command import ( + ModelDispatchBusCommand, +) +from omnibase_core.models.dispatch.model_dispatch_route import ModelDispatchRoute +from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope +from omnibase_infra.enums.enum_message_category import EnumMessageCategory +from omnibase_infra.event_bus.event_bus_inmemory import EventBusInmemory +from omnibase_infra.event_bus.models.model_event_message import ModelEventMessage +from omnibase_infra.runtime.dispatch_envelope_context import bind_dispatch_envelope +from omnibase_infra.runtime.message_dispatch_engine import MessageDispatchEngine +from omnibase_infra.runtime.runtime_local_ingress import ModelRuntimeLocalIngressRoute +from omnibase_infra.runtime.service_pattern_b_broker import RuntimePatternBBroker + +_PATTERN_B_TOPIC = "onex.cmd.omnibase-infra.pattern-b-dispatch.v1" # onex-topic-allow: the broker's own client command topic +_RESPONSE_TOPIC = "onex.evt.pattern-b.dispatch-completed.v1" # onex-topic-allow: the broker's own reply topic +_CONSUMED_TOPIC = "onex.cmd.test-service.consumed-command.v1" # onex-topic-allow: a local fixture topic for the engine seam +_CONSUMED_EVENT_TYPE = "test-service.consumed-command" + + +def _route() -> ModelRuntimeLocalIngressRoute: + return ModelRuntimeLocalIngressRoute( + node_name="node_delegation_orchestrator", + contract_name="delegation_orchestrator", + command_topic="onex.cmd.omnibase-infra.delegation-request.v1", + event_type="omnibase-infra.delegation-request", + terminal_event="onex.evt.omnibase-infra.delegation-completed.v1", + contract_path="/tmp/node_delegation_orchestrator/contract.yaml", # noqa: S108 + package_name="omnimarket", + ) + + +async def _start_broker_with_worker( + bus: EventBusInmemory, + route: ModelRuntimeLocalIngressRoute, + seen: asyncio.Queue[ModelEventMessage], +) -> RuntimePatternBBroker: + """Start the broker and a worker that terminalises whatever it consumes.""" + broker = RuntimePatternBBroker( + bus, + command_topic=_PATTERN_B_TOPIC, + routes={"delegation_orchestrator": route}, + ) + await broker.start() + + async def worker(message: ModelEventMessage) -> None: + if seen.empty(): + await seen.put(message) + envelope = ModelEventEnvelope[object].model_validate_json(message.value) + terminal = ModelEventEnvelope[object]( + payload={"status": "complete"}, + correlation_id=envelope.correlation_id, + envelope_timestamp=datetime.now(UTC), + event_type=route.terminal_event, + source_tool="delegation_orchestrator", + ) + await bus.publish( + route.terminal_event or "unknown", + None, + terminal.model_dump_json().encode("utf-8"), + None, + ) + + await bus.subscribe(route.command_topic, group_id="worker", on_message=worker) + return broker + + +def _command(correlation_id: UUID) -> ModelDispatchBusCommand: + return ModelDispatchBusCommand( + command_name="delegation_orchestrator", + requester="delegate_skill", + payload={"prompt": "alive"}, + correlation_id=correlation_id, + response_topic=_RESPONSE_TOPIC, + timeout_seconds=5, + ) + + +@pytest.mark.asyncio +async def test_worker_command_records_the_envelope_whose_dispatch_produced_it() -> None: + """Seam 1, the defect. A nested worker command is not a chain head. + + This is the production shape of ``service_delegation_dispatch_port``: the + delegate-skill handler is mid-dispatch on the ``delegate-skill`` command + when it asks the broker for a delegation, so the engine has that envelope + bound. Pre-fix the header and body parent assertions both fail while the + correlation assertion beside them passes — the edge was dropped, not the + identity. + """ + bus = EventBusInmemory(environment="test", group="pattern-b") + await bus.start() + route = _route() + seen: asyncio.Queue[ModelEventMessage] = asyncio.Queue(maxsize=1) + broker = await _start_broker_with_worker(bus, route, seen) + + correlation_id = uuid4() + consumed: ModelEventEnvelope[object] = ModelEventEnvelope( + payload={"prompt": "alive"}, + correlation_id=correlation_id, + envelope_timestamp=datetime.now(UTC), + event_type="omnimarket.delegate-skill", + source_tool="pattern-b-broker", + ) + + with bind_dispatch_envelope(consumed): + await broker.dispatch_request(_command(correlation_id)) + + message = await asyncio.wait_for(seen.get(), timeout=10) + published = ModelEventEnvelope[object].model_validate_json(message.value) + + # Positive control: the identity always arrived. A failure here is a + # broken fixture, not a regression of the causal edge. + assert published.correlation_id == correlation_id + assert message.headers.correlation_id == correlation_id + + # The defect. `event_ledger.onex_headers ->> 'parent_message_id'` is + # populated from the header, which `publish_envelope`'s identity binding + # derives from the envelope body. + assert published.parent_envelope_id == consumed.envelope_id + assert message.headers.parent_message_id == consumed.envelope_id + + await broker.stop() + await bus.close() + + +@pytest.mark.asyncio +async def test_worker_command_from_the_ingress_is_still_a_chain_head() -> None: + """Seam 1, the negative control. Nothing is invented. + + The HTTP ingress consumes no envelope, so the head hop must keep + publishing with no ``parent_message_id`` — the statement a verifier checks + the declared head against. A fix that stamped something here would make + "head" unfalsifiable, which is the same class of defect as the null it + replaces. + """ + bus = EventBusInmemory(environment="test", group="pattern-b") + await bus.start() + route = _route() + seen: asyncio.Queue[ModelEventMessage] = asyncio.Queue(maxsize=1) + broker = await _start_broker_with_worker(bus, route, seen) + + correlation_id = uuid4() + await broker.dispatch_request(_command(correlation_id)) + + message = await asyncio.wait_for(seen.get(), timeout=10) + published = ModelEventEnvelope[object].model_validate_json(message.value) + + assert published.correlation_id == correlation_id + assert published.parent_envelope_id is None + assert message.headers.parent_message_id is None + + await broker.stop() + await bus.close() + + +@pytest.mark.asyncio +async def test_causation_survives_the_engines_json_materialization() -> None: + """Seam 2, the defect, driven through the real dispatch engine. + + The dispatcher is invoked exactly as the auto-wiring boundary's stateful + wrapper is: with the materialized mapping. The positive control asserts + that the mapping really is attribute-less — reproducing the fallback's + cause — and the assertion after it is the fix. + """ + from omnibase_infra.runtime.auto_wiring.handler_wiring import ( + _consumed_envelope_id, + ) + + engine = MessageDispatchEngine() + observed: dict[str, object] = {} + + async def dispatcher(payload: object) -> None: + observed["payload"] = payload + observed["attribute_read"] = getattr(payload, "envelope_id", None) + observed["resolved"] = _consumed_envelope_id(payload) + + engine.register_dispatcher( + dispatcher_id="dispatcher-consumed", + dispatcher=dispatcher, + category=EnumMessageCategory.COMMAND, + message_types={_CONSUMED_EVENT_TYPE}, + ) + engine.register_route( + ModelDispatchRoute( + route_id="route.consumed", + topic_pattern="*.cmd.test-service.consumed-command.*", + message_category=EnumMessageCategory.COMMAND, + dispatcher_id="dispatcher-consumed", + ) + ) + engine.freeze() + + envelope: ModelEventEnvelope[object] = ModelEventEnvelope( + payload={"prompt": "alive"}, + correlation_id=uuid4(), + event_type=_CONSUMED_EVENT_TYPE, + ) + await engine.dispatch(_CONSUMED_TOPIC, envelope) + + # Positive control: the engine really does hand over a mapping with no + # `envelope_id` attribute. This is the line that made the old read return + # None on every live dispatch while every unit test that passed a real + # envelope kept working. + assert isinstance(observed["payload"], Mapping) + assert observed["attribute_read"] is None + + # The fix: the identity is read from the typed envelope the engine binds + # for exactly this purpose. + assert observed["resolved"] == envelope.envelope_id + + +@pytest.mark.asyncio +async def test_causation_is_none_when_nothing_was_consumed() -> None: + """Seam 2, the negative control. + + Outside a dispatch there is no consumed envelope, and the helper must say + so rather than reach for anything. ``None`` is what makes the outbox's + self-seeded fallback — used by the completion-bound sweep, which genuinely + has no causing envelope — still reachable. + """ + from omnibase_infra.runtime.auto_wiring.handler_wiring import ( + _consumed_envelope_id, + ) + + assert _consumed_envelope_id(object()) is None + assert _consumed_envelope_id({"envelope_id": "not-a-uuid"}) is None + + envelope: ModelEventEnvelope[object] = ModelEventEnvelope( + payload={"prompt": "alive"}, + correlation_id=uuid4(), + event_type=_CONSUMED_EVENT_TYPE, + ) + assert _consumed_envelope_id(envelope) == envelope.envelope_id diff --git a/tests/unit/nodes/node_delegation_chain_ledger_effect/test_chain_replay.py b/tests/unit/nodes/node_delegation_chain_ledger_effect/test_chain_replay.py index 7e177363db..a4f27467c1 100644 --- a/tests/unit/nodes/node_delegation_chain_ledger_effect/test_chain_replay.py +++ b/tests/unit/nodes/node_delegation_chain_ledger_effect/test_chain_replay.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2025 OmniNode.ai Inc. # SPDX-License-Identifier: MIT -"""Hermetic tests for the link-5 replay + tier-2 verifier (OMN-16964). +"""Hermetic tests for the link-5 replay + tier-2 verifier (OMN-16964, OMN-18419). These cover the four cases OMN-16964 acceptance item 4 names: complete chain replays green, a missing hop, a verifier SKIP, and a verifier that could not @@ -12,6 +12,14 @@ because it never ran the check. Every test below that asserts a non-passing outcome is asserting the absence of that defect, so none of them may be weakened into "returns something". + +OMN-18419 adds the second half: the declared topology is a TREE, and the +replay must grade each hop against the parent the DECLARATION names rather +than against whatever hop happened to precede it in time. The tree tests below +carry the real shape read off the .201 compose dev lane — a terminal that +branches off the head — plus the negative control that a genuinely wrong +parent still fails, because a grading rule that accepts a correct branch by +accepting anything is not a grading rule. """ from __future__ import annotations @@ -26,6 +34,9 @@ from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.enum_tier_two_verdict import ( EnumTierTwoVerdict, ) +from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.model_declared_chain_hop import ( + ModelDeclaredChainHop, +) from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models.model_observed_hop import ( ModelObservedHop, ) @@ -41,16 +52,38 @@ UNRELATED = UUID("bbbbbbbb-0000-0000-0000-00000000ffff") OTHER_CORRELATION = UUID("99999999-9999-9999-9999-999999999999") -DECLARED = ( +TOPICS = ( "onex.cmd.omnimarket.delegate-skill.v1", "onex.cmd.omnibase-infra.delegation-routing-request.v1", "onex.evt.omnibase-infra.routing-decision.v1", "onex.evt.omnimarket.delegate-skill-completed.v1", ) +# A LINE: every hop is caused by the one before it. Kept as its own fixture so +# the tree tests below are visibly a different topology and not a tweak. +DECLARED = ( + ModelDeclaredChainHop(topic=TOPICS[0], parent=None), + ModelDeclaredChainHop(topic=TOPICS[1], parent=TOPICS[0]), + ModelDeclaredChainHop(topic=TOPICS[2], parent=TOPICS[1]), + ModelDeclaredChainHop(topic=TOPICS[3], parent=TOPICS[2]), +) + +# The TREE the .201 dev lane actually produces: the terminal is a consequence +# of consuming the delegate-skill COMMAND, so it branches off the head rather +# than hanging off the routing decision that precedes it in time. +DECLARED_TREE = ( + ModelDeclaredChainHop(topic=TOPICS[0], parent=None), + ModelDeclaredChainHop(topic=TOPICS[1], parent=TOPICS[0]), + ModelDeclaredChainHop(topic=TOPICS[2], parent=TOPICS[1]), + ModelDeclaredChainHop(topic=TOPICS[3], parent=TOPICS[0]), +) + def _hop( - topic: str, envelope_id: str, parent: str, correlation: str = CORRELATION + topic: str, + envelope_id: UUID, + parent: UUID | None, + correlation: UUID = CORRELATION, ) -> ModelObservedHop: return ModelObservedHop( topic=topic, @@ -62,10 +95,20 @@ def _hop( def _complete_chain() -> tuple[ModelObservedHop, ...]: return ( - _hop(DECLARED[0], E0, None), - _hop(DECLARED[1], E1, E0), - _hop(DECLARED[2], E2, E1), - _hop(DECLARED[3], E3, E2), + _hop(TOPICS[0], E0, None), + _hop(TOPICS[1], E1, E0), + _hop(TOPICS[2], E2, E1), + _hop(TOPICS[3], E3, E2), + ) + + +def _observed_tree() -> tuple[ModelObservedHop, ...]: + """The observed chain whose last hop branches off the head.""" + return ( + _hop(TOPICS[0], E0, None), + _hop(TOPICS[1], E1, E0), + _hop(TOPICS[2], E2, E1), + _hop(TOPICS[3], E3, E0), ) @@ -75,7 +118,7 @@ def test_complete_chain_replays_green_and_verifies_pass() -> None: rows = assemble_replay_and_verify(CORRELATION, _complete_chain(), DECLARED) assert len(rows) == 4 - assert [row.hop for row in rows] == list(DECLARED) + assert [row.hop for row in rows] == list(TOPICS) assert [row.hop_index for row in rows] == [0, 1, 2, 3] assert all(row.replay_green for row in rows), [ (row.hop, row.replay_detail) for row in rows if not row.replay_green @@ -85,6 +128,123 @@ def test_complete_chain_replays_green_and_verifies_pass() -> None: assert rows[-1].verifier_verdict is EnumTierTwoVerdict.PASS +@pytest.mark.unit +def test_a_declared_tree_replays_green_when_a_hop_branches_off_the_head() -> None: + """OMN-18419 AC2. The exact chain the dev lane produces must grade green. + + This is the case the positional re-derivation got wrong: the terminal's + recorded parent IS an envelope observed on this correlation — the head — + and it was marked red solely because that envelope is not at ``index - 1``. + """ + rows = assemble_replay_and_verify(CORRELATION, _observed_tree(), DECLARED_TREE) + + assert all(row.replay_green for row in rows), [ + (row.hop, row.replay_detail) for row in rows if not row.replay_green + ] + assert rows[3].parent_envelope_id == E0 + assert rows[3].replay_detail == "" + assert all(row.verifier_verdict is EnumTierTwoVerdict.PASS for row in rows) + + +@pytest.mark.unit +def test_the_same_tree_graded_against_a_line_declaration_fails_the_branch() -> None: + """The falsifier for the test above: the grading is not vacuous. + + Same observed evidence, a declaration that says the terminal hangs off the + routing decision. The edge then genuinely does not close and the row is + red — which is what makes the green above a statement about the + DECLARATION and not about the replay having stopped checking. + """ + rows = assemble_replay_and_verify(CORRELATION, _observed_tree(), DECLARED) + + assert [row.replay_green for row in rows] == [True, True, True, False] + assert str(E2) in rows[3].replay_detail + assert str(E0) in rows[3].replay_detail + + +@pytest.mark.unit +def test_a_wrong_parent_still_fails_under_the_tree_declaration() -> None: + """The negative control. A parent that is not the declared hop's envelope. + + ``UNRELATED`` is not observed anywhere on this correlation, so no reading + of the topology can make this edge close. + """ + observed = ( + _hop(TOPICS[0], E0, None), + _hop(TOPICS[1], E1, E0), + _hop(TOPICS[2], E2, E1), + _hop(TOPICS[3], E3, UNRELATED), + ) + + rows = assemble_replay_and_verify(CORRELATION, observed, DECLARED_TREE) + + assert rows[3].replay_green is False + assert str(UNRELATED) in rows[3].replay_detail + # Not a verifier problem: the topology matched, the causal edge did not. + assert rows[3].verifier_verdict is EnumTierTwoVerdict.PASS + + +@pytest.mark.unit +def test_a_hop_that_records_no_parent_fails_when_one_is_declared() -> None: + """OMN-18419 AC1, at the grading tier. + + An absent ``parent_message_id`` is the checkable statement "this hop is a + chain HEAD". A hop the declaration says is caused by another must not be + able to assert that and pass — which is exactly what the live + ``delegation-routing-request`` hop was doing. + """ + observed = ( + _hop(TOPICS[0], E0, None), + _hop(TOPICS[1], E1, None), + _hop(TOPICS[2], E2, E1), + _hop(TOPICS[3], E3, E0), + ) + + rows = assemble_replay_and_verify(CORRELATION, observed, DECLARED_TREE) + + assert rows[1].replay_green is False + assert "records no parent" in rows[1].replay_detail + assert TOPICS[0] in rows[1].replay_detail + + +@pytest.mark.unit +def test_a_declared_head_that_records_a_parent_fails_the_replay() -> None: + """The head's claim is checked, not assumed. + + Before OMN-18419 the head was green by construction — there was no + predecessor to compare against — so a head carrying a parent went + unreported. + """ + observed = ( + _hop(TOPICS[0], E0, UNRELATED), + _hop(TOPICS[1], E1, E0), + _hop(TOPICS[2], E2, E1), + _hop(TOPICS[3], E3, E0), + ) + + rows = assemble_replay_and_verify(CORRELATION, observed, DECLARED_TREE) + + assert rows[0].replay_green is False + assert "head" in rows[0].replay_detail + + +@pytest.mark.unit +def test_a_declared_parent_that_was_never_observed_fails_the_replay() -> None: + """An edge cannot be re-derived from evidence that is not there.""" + observed = ( + _hop(TOPICS[0], E0, None), + # TOPICS[1] never happened, so TOPICS[2]'s declared parent is absent. + _hop(TOPICS[2], E2, E1), + _hop(TOPICS[3], E3, E0), + ) + + rows = assemble_replay_and_verify(CORRELATION, observed, DECLARED_TREE) + + assert rows[1].hop == TOPICS[2] + assert rows[1].replay_green is False + assert "not observed" in rows[1].replay_detail + + @pytest.mark.unit def test_missing_hop_is_absent_from_the_chain_and_never_silently_filled() -> None: """A hop that never happened must not appear as a row at all. @@ -94,16 +254,16 @@ def test_missing_hop_is_absent_from_the_chain_and_never_silently_filled() -> Non fabricated placeholder row would defeat that check outright. """ observed = ( - _hop(DECLARED[0], E0, None), - # DECLARED[1] never happened. - _hop(DECLARED[2], E2, E0), - _hop(DECLARED[3], E3, E2), + _hop(TOPICS[0], E0, None), + # TOPICS[1] never happened. + _hop(TOPICS[2], E2, E0), + _hop(TOPICS[3], E3, E2), ) rows = assemble_replay_and_verify(CORRELATION, observed, DECLARED) - assert [row.hop for row in rows] == [DECLARED[0], DECLARED[2], DECLARED[3]] - assert DECLARED[1] not in [row.hop for row in rows] + assert [row.hop for row in rows] == [TOPICS[0], TOPICS[2], TOPICS[3]] + assert TOPICS[1] not in [row.hop for row in rows] # The out-of-order arrival is a topology violation the tier-2 verifier sees. assert rows[1].verifier_verdict is EnumTierTwoVerdict.FAIL assert rows[-1].verifier_verdict is EnumTierTwoVerdict.FAIL @@ -113,14 +273,15 @@ def test_missing_hop_is_absent_from_the_chain_and_never_silently_filled() -> Non def test_broken_causal_link_fails_the_replay() -> None: """Replay is a re-derivation, not a copy of a stored flag. - Hop 2's recorded parent disagrees with hop 1's envelope id, so the chain - did not reproduce and replay_green is false for that hop. + Hop 2's recorded parent disagrees with the envelope observed on its + declared parent topic, so the chain did not reproduce and replay_green is + false for that hop. """ observed = ( - _hop(DECLARED[0], E0, None), - _hop(DECLARED[1], E1, E0), - _hop(DECLARED[2], E2, UNRELATED), - _hop(DECLARED[3], E3, E2), + _hop(TOPICS[0], E0, None), + _hop(TOPICS[1], E1, E0), + _hop(TOPICS[2], E2, UNRELATED), + _hop(TOPICS[3], E3, E2), ) rows = assemble_replay_and_verify(CORRELATION, observed, DECLARED) @@ -137,10 +298,10 @@ def test_broken_causal_link_fails_the_replay() -> None: def test_correlation_drift_mid_chain_fails_the_replay() -> None: """The OMN-16931 defect class: the correlation id changes mid-chain.""" observed = ( - _hop(DECLARED[0], E0, None), - _hop(DECLARED[1], E1, E0, correlation=OTHER_CORRELATION), - _hop(DECLARED[2], E2, E1), - _hop(DECLARED[3], E3, E2), + _hop(TOPICS[0], E0, None), + _hop(TOPICS[1], E1, E0, correlation=OTHER_CORRELATION), + _hop(TOPICS[2], E2, E1), + _hop(TOPICS[3], E3, E2), ) rows = assemble_replay_and_verify(CORRELATION, observed, DECLARED) @@ -150,11 +311,14 @@ def test_correlation_drift_mid_chain_fails_the_replay() -> None: @pytest.mark.unit -def test_verifier_skips_when_no_topology_is_declared_and_skip_is_not_pass() -> None: - """No declaration to verify against yields SKIP on every row. +def test_no_declaration_skips_tier_two_and_reds_tier_one_with_a_reason() -> None: + """No declaration to check against yields SKIP, and no green anywhere. This is the member the word "honest" in the OMN-16025 gate text exists - for. A verifier with nothing to check against has NOT passed. + for. A verifier with nothing to check against has NOT passed — and after + OMN-18419 neither has the replay, which now derives its expected parent + from the declaration rather than from the preceding position. A check that + could not run reports that it could not run. """ rows = assemble_replay_and_verify(CORRELATION, _complete_chain(), ()) @@ -162,8 +326,8 @@ def test_verifier_skips_when_no_topology_is_declared_and_skip_is_not_pass() -> N assert all(row.verifier_verdict is EnumTierTwoVerdict.SKIP for row in rows) assert rows[-1].verifier_verdict is not EnumTierTwoVerdict.PASS assert all(row.verifier_detail != "" for row in rows) - # The replay itself still ran — it needs no declaration. - assert all(row.replay_green for row in rows) + assert not any(row.replay_green for row in rows) + assert all("no declared chain topology" in row.replay_detail for row in rows) @pytest.mark.unit @@ -179,6 +343,9 @@ def test_verifier_skips_the_hops_the_declaration_does_not_reach() -> None: assert rows[1].verifier_verdict is EnumTierTwoVerdict.PASS assert rows[2].verifier_verdict is EnumTierTwoVerdict.SKIP assert rows[3].verifier_verdict is EnumTierTwoVerdict.SKIP + # Tier 1 reads the same declaration: the two unreached hops have no parent + # relation to re-derive, and say so. + assert [row.replay_green for row in rows] == [True, True, False, False] @pytest.mark.unit @@ -202,3 +369,10 @@ def test_verdict_never_upgrades_a_skip_to_a_pass_under_any_ordering() -> None: for index, row in enumerate(rows): if index >= len(declared): assert row.verifier_verdict is EnumTierTwoVerdict.SKIP + + +@pytest.mark.unit +def test_a_declared_hop_may_not_name_itself_as_its_own_cause() -> None: + """The declaration cannot ask for an edge the transport would reject.""" + with pytest.raises(ValueError, match="its own parent"): + ModelDeclaredChainHop(topic=TOPICS[0], parent=TOPICS[0]) diff --git a/tests/unit/nodes/node_delegation_chain_ledger_effect/test_handler_delegation_chain_ledger.py b/tests/unit/nodes/node_delegation_chain_ledger_effect/test_handler_delegation_chain_ledger.py index 64b7fc848c..2032fd2a40 100644 --- a/tests/unit/nodes/node_delegation_chain_ledger_effect/test_handler_delegation_chain_ledger.py +++ b/tests/unit/nodes/node_delegation_chain_ledger_effect/test_handler_delegation_chain_ledger.py @@ -24,12 +24,24 @@ ) from omnibase_infra.nodes.node_delegation_chain_ledger_effect.models import ( EnumTierTwoVerdict, + ModelDeclaredChainHop, ModelDelegationTerminalPayload, ModelLedgerChainRow, ModelObservedHop, ) -_CHAIN = ("command", "route-request", "route-decision", "completed") +# OMN-18419: the declaration is hops with a parent relation, not bare topics. +# This fixture is a LINE -- every hop caused by the one before it -- which is +# what `_complete_observation` below builds. The TREE cases are pinned in +# test_chain_replay.py, where the grading rule itself lives. +_CHAIN_TOPICS = ("command", "route-request", "route-decision", "completed") +_CHAIN = tuple( + ModelDeclaredChainHop( + topic=topic, + parent=None if index == 0 else _CHAIN_TOPICS[index - 1], + ) + for index, topic in enumerate(_CHAIN_TOPICS) +) _REPO_ROOT = Path(__file__).resolve().parents[4] _CONTRACT_PATH = ( _REPO_ROOT @@ -128,7 +140,9 @@ def test_this_node_contract_declares_no_undeliverable_output_model() -> None: _assert_no_bus_triggered_undeliverable_output_model(contract) -def _handler(declared_chain: tuple[str, ...] = _CHAIN) -> HandlerDelegationChainLedger: +def _handler( + declared_chain: tuple[ModelDeclaredChainHop, ...] = _CHAIN, +) -> HandlerDelegationChainLedger: handler = HandlerDelegationChainLedger( cast("ModelONEXContainer", object()), db_dsn="postgresql://test.invalid/test", @@ -150,7 +164,7 @@ def _request(correlation_id: UUID) -> ModelDelegationTerminalPayload: def _complete_observation( correlation_id: UUID, *, broken_at: int | None = None ) -> tuple[ModelObservedHop, ...]: - envelope_ids = tuple(uuid4() for _ in _CHAIN) + envelope_ids = tuple(uuid4() for _ in _CHAIN_TOPICS) return tuple( ModelObservedHop( topic=topic, @@ -164,7 +178,7 @@ def _complete_observation( ), correlation_id=correlation_id, ) - for index, topic in enumerate(_CHAIN) + for index, topic in enumerate(_CHAIN_TOPICS) ) @@ -211,7 +225,7 @@ async def test_complete_chain_writes_green_rows() -> None: assert len(rows) == 4 assert all(row.replay_green for row in rows) assert all(row.verifier_verdict is EnumTierTwoVerdict.PASS for row in rows) - assert {row.hop for row in rows} == set(_CHAIN) + assert {row.hop for row in rows} == set(_CHAIN_TOPICS) @pytest.mark.asyncio @@ -228,7 +242,7 @@ async def test_broken_edge_cannot_be_written_as_replay_green() -> None: assert output.result is None rows = persisted.await_args.args[0] - assert {row.hop for row in rows} == set(_CHAIN) + assert {row.hop for row in rows} == set(_CHAIN_TOPICS) assert rows[2].replay_green is False assert "causal link does not close" in rows[2].replay_detail @@ -316,7 +330,7 @@ async def test_absent_evidence_is_a_typed_refusal_not_a_silent_success() -> None message = str(excinfo.value) assert str(correlation_id) in message - for topic in _CHAIN: + for topic in _CHAIN_TOPICS: assert topic in message persisted.assert_not_awaited() @@ -351,10 +365,10 @@ async def test_upsert_that_changes_no_row_is_a_typed_refusal() -> None: row = ModelLedgerChainRow( correlation_id=correlation_id, hop_index=0, - hop=_CHAIN[0], + hop=_CHAIN_TOPICS[0], replay_green=True, verifier_verdict=EnumTierTwoVerdict.PASS, - observed_topic=_CHAIN[0], + observed_topic=_CHAIN_TOPICS[0], envelope_id=uuid4(), parent_envelope_id=None, replay_detail="", @@ -385,10 +399,10 @@ async def test_upsert_that_changes_a_row_is_accepted() -> None: row = ModelLedgerChainRow( correlation_id=correlation_id, hop_index=0, - hop=_CHAIN[0], + hop=_CHAIN_TOPICS[0], replay_green=True, verifier_verdict=EnumTierTwoVerdict.PASS, - observed_topic=_CHAIN[0], + observed_topic=_CHAIN_TOPICS[0], envelope_id=uuid4(), parent_envelope_id=None, replay_detail="", @@ -428,13 +442,16 @@ def test_ledger_projection_records_every_declared_chain_topic() -> None: entry["topic"] for entry in projection_contract["handler_routing"]["handlers"] } - missing = [t for t in chain_contract["chain_topology"] if t not in recorded] + # OMN-18419: `chain_topology` entries are declared hops, not bare topics. + declared_topics = [hop["topic"] for hop in chain_contract["chain_topology"]] + + missing = [t for t in declared_topics if t not in recorded] assert not missing, ( f"node_ledger_projection_compute does not record {missing!r}, so " "public.event_ledger can never carry the evidence " "node_delegation_chain_ledger_effect reads (OMN-18398)" ) - undispatched = [t for t in chain_contract["chain_topology"] if t not in dispatched] + undispatched = [t for t in declared_topics if t not in dispatched] assert not undispatched, ( f"{undispatched!r} are subscribed but have no handler_routing entry, " "which is subscribed-but-never-dispatched (OMN-14594 pairing rule)" diff --git a/tests/unit/nodes/test_node_ledger_projection_compute.py b/tests/unit/nodes/test_node_ledger_projection_compute.py index adce086e74..26c57c62ad 100644 --- a/tests/unit/nodes/test_node_ledger_projection_compute.py +++ b/tests/unit/nodes/test_node_ledger_projection_compute.py @@ -748,7 +748,7 @@ def contract_data(self) -> dict: with open(CONTRACT_PATH) as f: return yaml.safe_load(f) - def test_contract_has_all_24_dispatchable_topics(self, contract_data: dict) -> None: + def test_contract_has_all_25_dispatchable_topics(self, contract_data: dict) -> None: """Verify contract subscribes to every topic the runtime can deliver. 7 platform topic suffixes + 12 of the business command/completion/DLQ @@ -768,11 +768,19 @@ def test_contract_has_all_24_dispatchable_topics(self, contract_data: dict) -> N declares as its `chain_topology`. This node is the only writer of public.event_ledger, so while they were absent that node's evidence read was empty by construction and public.ledger_chain held zero rows. + + OMN-18419 added the FIFTH chain hop, + onex.cmd.omnibase-infra.delegation-request.v1 -- the pattern-B worker + command the runtime's delegation dispatch port publishes while consuming + the delegate-skill command. Absent here, the routing request's recorded + causal parent named an envelope no correlation-scoped read could + resolve, so the edge could not close and chain-canary link 5 graded a + correct chain red. """ event_bus = contract_data.get("event_bus", {}) topics = event_bus.get("subscribe_topics", []) - assert len(topics) == 24, f"Expected 24 topics, got {len(topics)}: {topics}" + assert len(topics) == 25, f"Expected 25 topics, got {len(topics)}: {topics}" # Verify expected topic suffixes/categories are covered expected_suffixes = [ diff --git a/tests/unit/runtime/test_ledger_projection_dispatch_reachability.py b/tests/unit/runtime/test_ledger_projection_dispatch_reachability.py index ac58f1bdf6..2bc5ed3651 100644 --- a/tests/unit/runtime/test_ledger_projection_dispatch_reachability.py +++ b/tests/unit/runtime/test_ledger_projection_dispatch_reachability.py @@ -131,7 +131,9 @@ async def test_ledger_projection_wires_when_result_applier_registered() -> None: deleted the six DLQ subscriptions whose names derive no message category (dispatch rejected every message on them), and OMN-18398 added the four delegation-chain topics the chain-ledger writer reads back out of - public.event_ledger, so wiring_count is 24, one per topic-scoped dispatcher. + public.event_ledger. OMN-18419 added the fifth chain hop, + delegation-request.v1, so wiring_count is 25, one per topic-scoped + dispatcher. """ outcome, wiring_count, reason = await _wire(with_applier=True) @@ -140,8 +142,8 @@ async def test_ledger_projection_wires_when_result_applier_registered() -> None: f"reason={reason!r}). A raw audit/projection contract that does not reach " "WIRED never creates a consumer, so event_ledger stays empty." ) - assert wiring_count == 24, ( - f"expected 24 wired handlers (1 per topic), got {wiring_count}" + assert wiring_count == 25, ( + f"expected 25 wired handlers (1 per topic), got {wiring_count}" )