Skip to content

fix(OMN-19817): the dispatch protocol declares no_escalation and the kwarg-parity reader resolves the consumer's TypedDict-typed splat - #4192

Merged
jonahgabriel merged 1 commit into
devfrom
jonah/omn-19817-kwarg-parity-no-escalation
Sep 27, 2026
Merged

jonahgabriel merged 1 commit into
devfrom
jonah/omn-19817-kwarg-parity-no-escalation

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

OMN-19817 (lineage: omnimarket#2841 and omnibase_infra#4088). Priority: this unblocks every omnibase_infra commit.

Since omnimarket#2841 merged at 2026-09-26T21:10Z, the always-run pre-commit hook onex-delegation-dispatch-consumer-kwarg-parity has failed 3 cases on every omnibase_infra commit, whatever the commit touches. omnimarket#2841 declared no_escalation on the consumer's ProtocolDelegationDispatchPort.dispatch and passes it as **_no_escalation_dispatch_kwargs(request). That is a module-level helper annotated to return _NoEscalationDispatchKwargs(TypedDict, total=False), and it adds the keyword only when it is true.

The splat is deliberate. The latest released omnibase_infra, v0.38.58, does not carry #4088, so an explicit no_escalation=False would raise TypeError on every delegation against a released port. For that reason the fix goes on this side and omnimarket is left alone.

The hook failed for two reasons:

  1. The ProtocolDelegationDispatchPort.dispatch protocol here did not declare no_escalation. RuntimeDelegationDispatchPort.dispatch has accepted it and put it on the published payload since feat(OMN-18931): dogfood fault-pin admission and typed terminal-evidence capture (K1 infra, salvaged from #3951) #4088. The protocol was the only half that had not been updated.
  2. The direction-3 call-site reader failed closed on any ** splat.

Changes

  • ProtocolDelegationDispatchPort.dispatch now takes no_escalation: bool = False, matching the implementation. It has a default, following the rule already written in that file.
  • _consumer_call_site_keywords reads exactly one splat shape: **helper(...), where helper is the only module-level def with that name, its return annotation names the only module-level class with that name, that class's only base is TypedDict, and its body holds annotated names plus an optional docstring. The keys go to a set of keywords the call may send, which never counts as keywords sent on every call. So direction 3, "nothing required here that the consumer does not pass", is exactly as strict as before. Every other splat still fails closed: a bare name, an attribute, a dict literal, a method call, an undefined or duplicate helper, an unannotated helper, a dict[...] annotation, a non-TypedDict class, an inherited TypedDict, or a body with other statements. There is a parametrized test for each of these.
  • New assertion test_runtime_port_accepts_every_keyword_the_call_site_can_send_including_splats, run for both the protocol and the implementation. Every keyword the call site can send, written out or splatted, must be accepted here. A key that arrives only through the splat is held to the same bar as one written out, so the resolved splat adds a check and removes none.

Test plan

Hook output before (fresh worktree of origin/dev at bc00160, reading the omnimarket clone at dev 6b7da747f):

FAILED ...::test_runtime_port_accepts_every_keyword_the_consumer_declares[protocol]  (does not accept ['no_escalation'])
FAILED ...::test_every_required_keyword_is_one_the_consumer_passes[protocol]        (splats **kwargs ... cannot be read statically)
FAILED ...::test_every_required_keyword_is_one_the_consumer_passes[implementation]  (same)
3 failed, 2 passed

After (head 946239e):

  • uv run pre-commit run onex-delegation-dispatch-consumer-kwarg-parity --all-files: Passed. The hook also passed inside this PR's own commit.
  • The module run against the omnimarket origin/dev handler through ONEX_DELEGATION_CONSUMER_SOURCE: 19 passed.
  • Negative control: adding an unaccepted bogus_key to the consumer's TypedDict fails the new assertion for both protocol and implementation (2 failed, 17 passed).
  • Negative control: reverting only the protocol change fails direction 1 and the new assertion for the protocol (2 failed, 17 passed).
  • Dispatch-seam focused tests: the parity module, test_delegation_dispatch_port_handler_compat, test_protocol_ownership, test_dispatch_port_budget_defaults_omn18924, test_omn18933_handler_wiring_route_scope and test_handler_wiring_resolver_integration: 68 passed.
  • ruff format, ruff check and mypy --strict are clean on both files. The pre-commit and pre-push hooks passed.

Lab-first: this PR does not affect the runtime. The only src change adds one defaulted parameter to a structural typing.Protocol that nothing calls at runtime. The implementation that runs on the lab is unchanged, so there is no lab surface to exercise, and no tenant, RLS or reader-authorization path is touched.

Runtime startup gate

  • N/A. This PR does not touch any of the above.

Type safety checklist

  • No new metadata["key"] or metadata.get("key") string literal access on Pydantic model fields
  • No new metadata: dict[str, Any] fields without TypedDict or # ONEX_EXCLUDE: comment
  • No new bare except Exception
  • N/A: no metadata dict keys added
  • N/A: no compose services added

Strict-gate ordering

  • No. This PR introduces or tightens no gate that a downstream consumer does not already meet. The new assertion passes against the current omnimarket dev consumer.

Related issues

OMN-19817. Lineage: omnimarket#2841 and omnibase_infra#4088 (the no_escalation work this ticket is a child of), and the earlier dispatch-port parity incidents recorded in the parity module's docstring.

Evidence-Ticket: OMN-19817
Evidence-Source: OCC#11540

…kwarg-parity reader resolves the consumer's TypedDict-typed splat

omnimarket#2841 (OMN-18931) declared no_escalation on the consumer protocol and
passes it as **_no_escalation_dispatch_kwargs(request), a module-level helper
annotated to return a module-level TypedDict, so a released omnibase_infra port
predating the keyword keeps working. The always-run consumer-kwarg-parity hook
then failed 3 cases on every omnibase_infra commit: the protocol lacked the
keyword (the implementation has accepted it since #4088), and the call-site
reader failed closed on any splat.

- ProtocolDelegationDispatchPort.dispatch gains no_escalation: bool = False.
- The call-site reader resolves exactly that splat shape to the TypedDict's
  keys, records them as conditional (never counted as passed for direction 3),
  and still fails closed on every other splat.
- A new assertion holds every keyword the call site can send, explicit or
  splatted, to what the protocol and implementation accept.

Onex-Lane: kwarg-parity-fix-83
Onex-Session: 097bff177c7b49ccbb1b5aa566dacfd7
jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 26, 2026
…ibase_infra#4192 (#11540)

* evidence(OMN-19817): author OCC companion for OmniNode-ai/omnibase_infra#4192

OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head 946239e98f75cfdd509cb89e9bb2f015ef0b2ed0.

* evidence(OMN-19817): self-bind OCC#11540 + rebind contract_sha256

---------

Co-authored-by: omnimarket-bot <bot@omninode.ai>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hostile Reviewer — adversarial findings (OMN-17492)

Models succeeded: qwen3-review, gpt-oss-review
Models failed: none
New finding threads: 0
Deduped (already posted on this PR): 0
Below quorum (one model only, reported not threaded): 10
Nit-level findings suppressed: 1

The model is the FINDER, never the gate: merge is gated only by the
deterministic Hostile Review Thread Gate, which blocks while
hostile-reviewer threads are unresolved. Resolve each thread after
addressing (or rejecting, with a reply) its finding.

Below quorum: 10 finding(s) raised by one model only (OMN-18479)

These are reported and NOT dropped, but they get no thread and do not block: a single model's finding no other model reproduced is not evidence enough to stop a merge. Read them; act on them if they are right.

  • [MAJOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py, _typed_dict_splat_keys (qwen3-review) — Splat resolution silently ignores helper arguments, enabling false-negative parity | The new _typed_dict_splat_keys resolver accepts any call of the form **_helper(request) as long as _helper is
  • [MAJOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py, _consumer_call_site_keywords (qwen3-review) — Conditional keys are subtracted from passed, but the subtraction is asymmetric and undocumented | In _consumer_call_site_keywords, the return is `_CallSiteKeywords(passed=frozenset(passed), conditio
  • [MAJOR] src/omnibase_infra/runtime/protocols/protocol_delegation_dispatch_port.py (gpt-oss-review) — Added positional parameter shifts existing call signatures | The new no_escalation argument is inserted before response_contract in the dispatch function signature. Callers that invoke `dispatch
  • [MAJOR] src/omnibase_infra/runtime/protocols/protocol_delegation_dispatch_port.py (gpt-oss-review) — no_escalation flag is accepted but never used | The added no_escalation parameter is part of the public API but the function body does not reference it. Consumers may set the flag expecting the ru
  • [MINOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py, _consumer_call_site_keywords (qwen3-review) — AST-based static analysis of consumer source is brittle and can be bypassed by obfuscation | The entire parity check relies on ast.parse of the consumer's source file. This is a static analysis that
  • [MINOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py, _OPAQUE_SPLATS (qwen3-review) — No test for the case where the TypedDict has zero keys | The _typed_dict_splat_keys function raises an AssertionError if not keys, but there is no test case in _OPAQUE_SPLATS for a TypedDict w
  • [MINOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py, _SPLAT_HELPER_SOURCE (qwen3-review) — The resolver does not handle TypedDict with total=True (the default) | The test source _SPLAT_HELPER_SOURCE uses class _Kwargs(TypedDict, total=False):. The resolver checks that the base is `Typ
  • [MINOR] src/omnibase_infra/runtime/protocols/protocol_delegation_dispatch_port.py (gpt-oss-review) — Missing docstring for new no_escalation argument | The new keyword is introduced without any inline documentation explaining its purpose, default behavior, or interaction with existing escalation me
  • [MINOR] tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (gpt-oss-review) — Integration tests perform extensive AST parsing for each run | The new test suite parses consumer source files with the ast module for every test case, which can noticeably increase CI execution tim
  • [MINOR] tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (gpt-oss-review) — Tests rely on source‑file location and exact string replacements | The test suite constructs temporary consumer files by performing string replacements on a base source snippet. Any change to formatti

@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ Hostile Reviewer — REVIEWED

Critical findings: 0
Major findings: 4
Total findings: 10
Models succeeded: qwen3-review,gpt-oss-review
Models unavailable: none

Action required: findings were posted as review threads. Address or reject each one, then resolve its thread — the Hostile Review Thread Gate fails while hostile-reviewer threads are unresolved (OMN-17492).


Semantics (OMN-17492 — the model finds, thread resolution gates)

Surface Meaning Blocks merge?
Review threads Per-finding, posted by the reviewer No (informational)
Hostile Review Thread Gate Deterministic: unresolved hostile-reviewer threads exist Fails until resolved (not yet a required context)
degraded verdict Fewer than 2 models succeeded (infra) Fails this job with a named reason

Powered by omniintelligence.review_pairing.cli_review — multi-model adversarial review: qwen3-review (Qwen3.8-27B), gpt-oss-review (gpt-oss-120b) (OMN-8468/OMN-8524/OMN-17492)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hostile Reviewer — adversarial findings (OMN-17492)

Models succeeded: qwen3-review, gpt-oss-review
Models failed: none
New finding threads: 0
Deduped (already posted on this PR): 0
Below quorum (one model only, reported not threaded): 10
Nit-level findings suppressed: 0

The model is the FINDER, never the gate: merge is gated only by the
deterministic Hostile Review Thread Gate, which blocks while
hostile-reviewer threads are unresolved. Resolve each thread after
addressing (or rejecting, with a reply) its finding.

Below quorum: 10 finding(s) raised by one model only (OMN-18479)

These are reported and NOT dropped, but they get no thread and do not block: a single model's finding no other model reproduced is not evidence enough to stop a merge. Read them; act on them if they are right.

  • [MAJOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (qwen3-review) — Splat resolution ignores helper arguments, enabling false-negative parity | The new _typed_dict_splat_keys resolver treats any call to a module-level helper returning a TypedDict as resolvable, but
  • [MAJOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (qwen3-review) — Resolver does not handle forward references or string annotations for TypedDict | The resolver _typed_dict_splat_keys handles ast.Name and ast.Constant (string) annotations for the helper's retu
  • [MAJOR] src/omnibase_infra/runtime/protocols/protocol_delegation_dispatch_port.py (gpt-oss-review) — Added no_escalation parameter is never used | The dispatch function signature now includes a no_escalation boolean flag with a default value, but the implementation does not reference this argument. C
  • [MAJOR] src/omnibase_infra/runtime/protocols/protocol_delegation_dispatch_port.py (gpt-oss-review) — Signature change not reflected in RuntimeDelegationDispatchPort | The protocol definition now accepts a no_escalation keyword, but the RuntimeDelegationDispatchPort implementation is unchanged in this
  • [MINOR] src/omnibase_infra/runtime/protocols/protocol_delegation_dispatch_port.py (qwen3-review) — No security vulnerability, but fail-closed posture is correct | The change introduces a static analysis tool that resolves TypedDict splats. The fail-closed posture (raising AssertionError on unresolv
  • [MINOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (qwen3-review) — Test for opaque splats uses string replacement, which is fragile | The test test_splat_reader_still_fails_closed_on_every_other_splat uses string replacement on _SPLAT_HELPER_SOURCE to create vari
  • [MINOR] src/tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (qwen3-review) — Static analysis in tests couples test to consumer's internal implementation | The test test_runtime_port_accepts_every_keyword_the_call_site_can_send_including_splats reads the consumer's source cod
  • [MINOR] tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (gpt-oss-review) — Duplicate definition of _consumer_passed_keywords | The test module defines _consumer_passed_keywords twice: an original implementation returning a set of passed keywords, and a later redefinition tha
  • [MINOR] tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (gpt-oss-review) — AST parsing of consumer source in each test iteration | The helper _consumer_call_site_keywords parses the entire consumer source file with ast.parse for every test that invokes it. This adds unnecess
  • [MINOR] tests/integration/runtime/test_delegation_dispatch_port_consumer_kwarg_parity.py (gpt-oss-review) — Signature inspection may include implicit parameters | The test test_runtime_port_accepts_every_keyword_the_call_site_can_send_including_splats obtains accepted parameters via inspect.signature(dispat

@jonahgabriel
jonahgabriel added this pull request to the merge queue Sep 27, 2026
@jonahgabriel
jonahgabriel removed this pull request from the merge queue due to a manual request Sep 27, 2026
@jonahgabriel
jonahgabriel added this pull request to the merge queue Sep 27, 2026
Merged via the queue into dev with commit 15ec305 Sep 27, 2026
249 of 262 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-19817-kwarg-parity-no-escalation branch September 27, 2026 02:42
jonahgabriel pushed a commit that referenced this pull request Sep 27, 2026
…erge

Concludes the in-flight merge of origin/dev's queued omnimarket pin advance
(OMN-17292, #4164) with the vendored session_content projection migration.
Pulls the OMN-19817/#4192 dispatch-protocol no_escalation fix's own two
files verbatim from dev's fix commit so the always_run consumer-kwarg-parity
hook, unrelated to this PR's own diff, no longer blocks the commit.

Onex-Lane: repo-drain-omnimarket-pr
Onex-Session: 6166a1801d9e4059bc4a41476e0f1299
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant