Skip to content

fix(OMN-16840): refuse a delegation class the routing authority declares it cannot serve - #296

Merged
jonahgabriel merged 2 commits into
devfrom
jonah/omn-16840-delegation-task-type-routing-availability
Aug 28, 2026
Merged

jonahgabriel merged 2 commits into
devfrom
jonah/omn-16840-delegation-task-type-routing-availability

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Aug 28, 2026 •

Copy link
Copy Markdown
Contributor

OMN-16840

Residual of OMN-16811. Its fix (omnimarket#2179, merged 2026-08-28) declared the agent_delegation capability gap in the routing authority's own contract:

# omnimarket/src/omnimarket/configs/task_class_contracts.v1.yaml
routing_availability:
  status: pending_capability
  missing_capability: agent_orchestration
  tracking: "OMN-15961 WS-4/C6"
  reason: >-
    No routing tier can execute agentic/tool-using work; every tier is an
    HTTP chat-completion backend. ...

with the stated intent that "a consumer (dashboard menu, gateway admission) refuse the class up front instead of offering it and hanging for the full ingress budget." No consumer read it. The dashboard kept offering agent_delegation, POST /api/delegation/trigger kept publishing the envelope, and the caller waited out the full ingress budget for an ONEX_CORE_041_INVALID_CONFIGURATION that was knowable before dispatch.

What changed

  • shared/contracts/delegation-task-types.json mirrors the upstream declaration verbatim on agent_delegation.
  • shared/types/delegation-task-availability.ts — the browser-side reading. Undeclared availability is availability, so the other 12 classes are untouched.
  • DelegationTriggerPanel disables the option and renders the contract's own reason. The dashboard renders the declaration; it does not author an availability rule.
  • POST /api/delegation/trigger answers 409 task_type_unavailable with the declared reason / missing_capability / tracking and retryable: false, and does not publish.

No new REST surface, no new authority. Both halves read the contract that was already imported here.

Why two readings, not one module

shared/types/* files consumed by the server belong to the composite tsconfig.node.json project and are excluded from the root project; a single module in both trips TS6305/TS6307, whichever way it is placed (verified both directions locally). The contract JSON is therefore the shared authority. refuses exactly the classes the contract declares unavailable derives the route's refusal set from that JSON rather than from a literal, so adding or removing a declaration moves the route with no edit to the test or the handler.

Evidence (local, this branch)

  • Red first: c23c0b6 committed the two failing assertions (option enabled, route returns 200). The two companion assertions — escalation stays selectable, escalation still dispatches — passed at red, so only the new behaviour was failing.
  • Green: 93fb274.
  • npx vitest run server/__tests__/dispatch.test.ts src/.../DelegationTriggerPanel.test.tsx → 28 passed.
  • npm run test:run → 1656 passed / 15 skipped, 178 files.
  • npm run check (root tsc) clean; npm run build:server (tsconfig.node.json) clean; npm run lint clean; pre-commit full hook set passed on both commits.

Acceptance criteria

  1. routing_availability present on agent_delegation in the omnidash contract — met.
  2. Component test: agent_delegation disabled + declared reason visible; escalation enabled — met (2 tests).
  3. Trigger route refuses a declared-unavailable class with the declared reason, without publishing — met (refuses a task_type the contract declares routing-unavailable).
  4. Classes with no declaration are unaffected — met (still dispatches a task_type with no routing_availability declaration + the contract-derived symmetry test covering all 13).

Scope

Dashboard/API-surface only. No lane mutation; no claim about stability-test, judge, or prod. When the agent_orchestration producer lands and the upstream declaration is deleted, deleting it here re-opens the class.

Evidence-Ticket: OMN-16840
Evidence-Source: OCC#7402

Summary by CodeRabbit

  • New Features
    • Added routing availability indicators for delegation task types.
    • Unavailable task types remain visible but are disabled, with an explanation shown in the interface.
    • Available task types continue to support normal selection and dispatch.
  • Bug Fixes
    • Prevented unavailable delegation requests from reaching execution.
    • Requests for unavailable task types now return a non-retryable 409 response with availability details.
    • Task types without availability restrictions continue to dispatch successfully.

…authority declares unavailable

The routing authority declares agent_delegation
routing_availability.status=pending_capability (omnimarket
task_class_contracts.v1.yaml, omnimarket#2179) precisely so a consumer can
refuse the class up front. No omnidash consumer reads it.

Two failing assertions:
- the agent_delegation option renders enabled with no reason surfaced
- POST /api/delegation/trigger returns 200 and publishes the envelope

Both companion assertions (escalation stays selectable, escalation still
dispatches) already pass, so the red is the new behaviour only.
…res it cannot serve

The routing authority declares agent_delegation
routing_availability.status=pending_capability (omnimarket
task_class_contracts.v1.yaml, omnimarket#2179) with the stated intent that a
consumer refuse the class up front. Nothing read it, so the menu offered the
class, the trigger route published the envelope, and the caller waited out the
full ingress budget for an ONEX_CORE_041 that was knowable before dispatch.

- shared/contracts/delegation-task-types.json mirrors the declaration verbatim
- the task-type menu disables the option and renders the contract's own reason
- POST /api/delegation/trigger answers 409 task_type_unavailable with the
  declared reason/missing_capability/tracking and does not publish

Undeclared availability is availability, so the other 12 classes are untouched.
The browser and server halves read the same contract block but cannot share one
module: shared/types files consumed by the server belong to the composite
tsconfig.node.json project and are excluded from the root project, so one module
cannot be typechecked by both. The contract JSON is the shared authority, and
'refuses exactly the classes the contract declares unavailable' derives the
route's refusal set from that JSON rather than from a literal, so a class added
to or removed from the declaration moves this route with no edit here.

When the agent_orchestration producer lands (OMN-15961 WS-4/C6) and the upstream
declaration is deleted, deleting it here re-opens the class.
@onexbot-occ-writer

Copy link
Copy Markdown
Contributor

OCC autobind did not mint a companion for this PR: no changed-file candidate could be proven RED against the merge base, and emitting a PR-existence probe instead would be non-falsifiable evidence (OMN-15247). Hand-authored evidence is required.

@coderabbitai

coderabbitai Bot commented Aug 28, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46389e55-309e-4781-b1da-7571ca0d7de5

📥 Commits

Reviewing files that changed from the base of the PR and between 56139db and 93fb274.

📒 Files selected for processing (6)
  • server/__tests__/dispatch.test.ts
  • server/routes.ts
  • shared/contracts/delegation-task-types.json
  • shared/types/delegation-task-availability.ts
  • src/components/dashboard/delegation-control-plane/DelegationTriggerPanel.test.tsx
  • src/components/dashboard/delegation-control-plane/DelegationTriggerPanel.tsx

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.


📝 Walkthrough

Walkthrough

The change adds shared routing availability metadata for delegation task types. The server rejects unavailable types before runtime dispatch. The dashboard disables those types and displays contract-provided reasons. Tests cover server and dashboard behavior.

Changes

Delegation availability

Layer / File(s) Summary
Availability contract and helpers
shared/contracts/delegation-task-types.json, shared/types/delegation-task-availability.ts
The contract declares routing availability for agent_delegation. Shared types and helpers determine routability and unavailable reasons.
Server routing enforcement and coverage
server/routes.ts, server/__tests__/dispatch.test.ts
The trigger endpoint returns a non-retryable 409 for unavailable task types before runtime dispatch. Tests cover declared unavailable types and undeclared routable types.
Dashboard routing selection
src/components/dashboard/delegation-control-plane/DelegationTriggerPanel.tsx, src/components/dashboard/delegation-control-plane/DelegationTriggerPanel.test.tsx
Unavailable task types remain visible but disabled. Their contract reasons are displayed. Tests confirm escalation remains selectable.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 93fb2

The dashboard and trigger endpoint now refuse unavailable delegation classes before dispatch and preserve existing behavior for other classes; no actionable merge-blocking risk remains.

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant DelegationTriggerPanel
  participant TriggerEndpoint
  participant TaskAvailability
  participant Runtime
  Operator->>DelegationTriggerPanel: select task type
  DelegationTriggerPanel->>TaskAvailability: read routing availability
  TaskAvailability-->>DelegationTriggerPanel: enabled or disabled state
  Operator->>TriggerEndpoint: submit routable task type
  TriggerEndpoint->>TaskAvailability: validate routing availability
  TaskAvailability-->>TriggerEndpoint: routable
  TriggerEndpoint->>Runtime: dispatch task
  Runtime-->>TriggerEndpoint: dispatch result
  TriggerEndpoint-->>Operator: response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 5 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: refusing delegation classes that the routing authority declares unavailable.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 5 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jonah/omn-16840-delegation-task-type-routing-availability

Comment @coderabbitai help to get the list of available commands.

jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Aug 28, 2026
* evidence: OCC companion pass 1 for OmniNode-ai/omnidash#296

* evidence: OCC companion self-bind for #7402

---------

Co-authored-by: node-occ-companion-effect <occ-companion-effect@omninode.ai>
@jonahgabriel
jonahgabriel merged commit af2fbd5 into dev Aug 28, 2026
40 of 43 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-16840-delegation-task-type-routing-availability branch August 28, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant