Skip to content

AMPR-216: T3 — Typed failure + RoutingEvent when no model meets the floor - #580

Merged
wow-miley merged 1 commit into
mainfrom
miley/ampr-216-t3-typed-failure-routingevent-when-no-model-meets-the-floor
Jun 15, 2026
Merged

AMPR-216: T3 — Typed failure + RoutingEvent when no model meets the floor#580
wow-miley merged 1 commit into
mainfrom
miley/ampr-216-t3-typed-failure-routingevent-when-no-model-meets-the-floor

Conversation

@wow-miley

Copy link
Copy Markdown
Contributor

Summary

  • Makes RoutingResolution a sealed interface (Success | FloorUnmet) so a rung floor that no registered model satisfies is a typed, terminal result — not a silent downgrade
  • Adds RoutingEvent.RouteFloorUnmet (HIGH urgency) emitted on EventSerialBus alongside existing routing events, carrying requestedFloor and bestAvailableRung for diagnostics
  • CognitiveRelayImpl.resolve throws RoutingFloorUnmetException; resolveWithMetadata returns FloorUnmet — callers choose which API surface to use
  • AgentLLMService throws RoutingFloorUnmetException rather than silently falling through to a sub-floor config

Changes

  • RoutingResolution → sealed interface (Success, FloorUnmet) in CognitiveRelay.kt
  • RouteFloorUnmet data class added to RoutingEvent.kt
  • RoutingFloorUnmetException (new file) for the resolve() throw path
  • CognitiveRelayImpl: floor-unmet detection + emitRouteFloorUnmet + bestRungAmongCapabilityRules helper
  • SignificanceAwareEventLogger: RouteFloorUnmetSIGNIFICANT
  • AgentLLMService: handles FloorUnmet sealed variant
  • CognitiveRelayPassthrough, CognitiveRelayCapabilityTest, CognitiveRelayCostTest, CognitiveRelayImplTest, RoutingEventTest: updated for sealed RoutingResolution
  • CognitiveRelayFloorTest (new): 8 tests covering all validation criteria from the ticket

Test plan

  • FloorUnmet returned when minRung = THREE and best available is rung TWO
  • Success returned when a rung THREE model exists and matches
  • Floor-unmet is terminal — no sub-floor AIConfiguration produced
  • resolve() throws RoutingFloorUnmetException with correct requestedFloor / bestAvailableRung
  • RouteFloorUnmet event emitted on EventSerialBus with correct fields
  • RouteSelected NOT emitted when floor is unmet
  • null bestAvailableRung when registry has no descriptors for the configured rules
  • No regression: no minRung requirement resolves to Success normally

Closes: AMPR-216 · Depends on: #577 (T2)

🤖 Generated with Claude Code

…loor

Adds RoutingResolution.FloorUnmet sealed variant and RouteFloorUnmet event
so a rung floor that no model satisfies is terminal and never silently
downgrades to a sub-floor AIConfiguration.

- RoutingResolution → sealed interface (Success | FloorUnmet)
- RouteFloorUnmet event (HIGH urgency) emitted on EventSerialBus alongside
  existing RouteSelected/RouteFallback/RouteResolved events
- CognitiveRelayImpl.resolveWithMetadata detects floor-unmet when minRung
  is set and no ByCapability rule's descriptor meets it; bestAvailableRung
  carried for diagnostics
- CognitiveRelayImpl.resolve throws RoutingFloorUnmetException on FloorUnmet
- AgentLLMService throws RoutingFloorUnmetException rather than silently
  downgrading when resolveWithMetadata returns FloorUnmet
- SignificanceAwareEventLogger handles RouteFloorUnmet as SIGNIFICANT
- CognitiveRelayFloorTest: 8 tests covering FloorUnmet result, terminal
  behaviour, exception throw, event emission, and no-floor-unmet for
  satisfiable or floor-absent requirements
- Existing resolveWithMetadata call sites updated for sealed return type

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Concept staleness check — 4 warning(s).

These changes touched files listed under a concept's tracked_sources without updating the concept file. Either update the concept (and bump last_verified) or include a Concept-Verified: <ConceptName> trailer in a commit on this PR.

Validator output
⚠ Concept 'CognitionTrace' may be stale: ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/domain/event/RoutingEvent.kt matches tracked_sources pattern ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/domain/event/RoutingEvent.kt but docs/concepts/cognition-trace.md was not modified.
⚠ Concept 'CognitiveRelay' may be stale: ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/domain/routing/CognitiveRelay.kt matches tracked_sources pattern ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/domain/routing/** but docs/concepts/cognitive-relay.md was not modified.
⚠ Concept 'EventSerialBus' may be stale: ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/events/utils/SignificanceAwareEventLogger.kt matches tracked_sources pattern ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/events/utils/SignificanceAwareEventLogger.kt but docs/concepts/event-serial-bus.md was not modified.
⚠ Concept 'PropelLoop' may be stale: ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/domain/reasoning/AgentLLMService.kt matches tracked_sources pattern ampere-core/src/commonMain/kotlin/link/socket/ampere/agents/domain/reasoning/** but docs/concepts/propel-loop.md was not modified.

validate-concepts: 4 warning(s). Validator informs; never blocks.

@wow-miley
wow-miley merged commit 8447d6a into main Jun 15, 2026
2 of 3 checks passed
@wow-miley
wow-miley deleted the miley/ampr-216-t3-typed-failure-routingevent-when-no-model-meets-the-floor branch June 15, 2026 05:55
wow-miley added a commit that referenced this pull request Jun 15, 2026
#580 added RoutingEvent.RouteFloorUnmet to the sealed hierarchy but left the
ampere-cli when-expressions non-exhaustive, breaking :ampere-cli:compileKotlinJvm
on main. Now that the activated CODE path actually emits RouteFloorUnmet, the CLI
must render it:

- EventCategorizer: classify RouteFloorUnmet as CRITICAL (terminal routing
  failure needing human awareness).
- EventRenderer: 🔀 in red, matching the routing-event icon family.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
wow-miley added a commit that referenced this pull request Jun 15, 2026
#580 added RoutingEvent.RouteFloorUnmet to the sealed hierarchy but left the
ampere-cli when-expressions non-exhaustive, breaking :ampere-cli:compileKotlinJvm
on main. Now that the activated CODE path actually emits RouteFloorUnmet, the CLI
must render it:

- EventCategorizer: classify RouteFloorUnmet as CRITICAL (terminal routing
  failure needing human awareness).
- EventRenderer: 🔀 in red, matching the routing-event icon family.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
wow-miley added a commit that referenced this pull request Jun 15, 2026
…582)

* AMPR-219: T6 — Activate the relay in the CODE production agent path

Wire the capability/cost-aware CognitiveRelay into one real bundled agent
path (SparkBasedAgent.Code, built by AgentFactory for AgentType.CODE) so the
full selection seam runs live: AgentDefinition.minimumRung floor ->
RoutingContext -> resolveWithMetadata -> model-keyed cost-aware selection ->
outbound client. Manual constructor injection, no Koin.

- SparkBasedAgent: new _cognitiveRelay/_minimumRung params threaded into the
  agentConfiguration getter and the Code factory.
- CapabilityRoutingDefaults (new): one ByCapability rule per bundled cloud
  model, in lockstep with the registry seed, so a declared floor is satisfiable.
- AgentFactory: builds a real CognitiveRelayImpl + InMemoryModelDescriptorRegistry
  over the shared eventSerialBus, wired into the CODE path only (THREE floor).
  PRODUCT/PROJECT/QUALITY stay dormant (null relay).
- AgentDefinition.Custom: carries minimumRung (defaults null, non-breaking).

SparkBasedAgentRelayActivationTest drives a real Code agent end-to-end:
resolves to Gemini 2.5 Pro respecting the floor, emits RouteSelected +
RouteResolved, and an unsatisfiable floor throws RoutingFloorUnmetException +
emits RouteFloorUnmet with no downgrade.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* AMPR-219: Handle RouteFloorUnmet in CLI event when-expressions

#580 added RoutingEvent.RouteFloorUnmet to the sealed hierarchy but left the
ampere-cli when-expressions non-exhaustive, breaking :ampere-cli:compileKotlinJvm
on main. Now that the activated CODE path actually emits RouteFloorUnmet, the CLI
must render it:

- EventCategorizer: classify RouteFloorUnmet as CRITICAL (terminal routing
  failure needing human awareness).
- EventRenderer: 🔀 in red, matching the routing-event icon family.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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