Skip to content

fix(hooks-session-naming): fall back to priority provider on role-resolution empty - #305

Merged
Salil Das (sadlilas) merged 1 commit into
mainfrom
fix/session-naming-role-fallback
Aug 18, 2026
Merged

fix(hooks-session-naming): fall back to priority provider on role-resolution empty#305
Salil Das (sadlilas) merged 1 commit into
mainfrom
fix/session-naming-role-fallback

Conversation

@bkrabach

Copy link
Copy Markdown
Collaborator

Summary

This is cross-platform behavior, not Windows work — behavior tests passed on both platforms. It's drafted here to separate it from the Windows queue and stay focused.

When hooks-session-naming resolves a model_role and gets a clean empty result (zero candidates), the code previously returned None and skipped session naming entirely. The feature then silently never ran, making the system harder to reason about and harder to test.

This change falls back to the session's normal priority provider when role resolution returns cleanly empty, logs a warning naming both the role that failed to resolve and the provider actually substituted, then fires naming once per session (subsequent calls drop to DEBUG).

Relationship to PR #300

This deliberately narrows, and does not undo, PR #300 (fix(hooks): session-naming abort on role-resolution failure, not silent downgrade):

  • Resolver raises an exception → still aborts. Unchanged. An exception is an unknown, possibly transient failure; falling back there could quietly route onto the expensive model on every retry — exactly the cost leak fix(hooks): session-naming abort on role-resolution failure, not silent downgrade #300 was written to stop.
  • Resolver returns cleanly empty → now falls back loudly. This is a deterministic config gap. No amount of retrying will produce a candidate, so aborting just means the feature never runs.

Why this matters

This silent skip confounded a platform A/B test. A Linux run showed zero errors not because a bug was absent, but because naming had silently skipped and never exercised the code path. The Windows run had a fast candidate, ran naming, and surfaced a real provider-lifecycle defect (now PR #93 on amplifier-module-provider-anthropic). Two runs, same command, different code paths — and the log line explaining it went unread.

A feature that silently doesn't run makes the system harder to reason about and harder to test.

Evidence

Real teeth check — the behavior alone was reverted (new method signature kept, so failures are behavioral rather than TypeError):

skip behavior restored:  3 failed, 23 passed
    test_resolver_empty_result_falls_back_to_priority_provider
    test_resolver_empty_result_warns_once_per_session
    test_resolver_empty_result_logs_warning
with the fix:            26 passed

Suites: repo root 1549 passed before and after. Module suite 25 → 26 passed. Ruff clean A/B via git stash.

Note: test_resolver_empty_result_aborts_without_calling_provider was rewritten — it asserted result is None and not priority_provider.complete.called, directly encoding the behavior being replaced.

Out of scope

If resolved is non-empty but no entry in providers matches the resolved name, the loop falls through to the generic fallback with no warning at all — a related silent gap, left untouched as out of scope.

…olution empty, not silent skip

When hooks-session-naming resolves a model_role and gets a clean empty result
(zero candidates), the code previously returned None and skipped session naming
entirely. The feature then silently never ran, making the system harder to
reason about and harder to test. A deterministic config gap should fail loud,
not silent.

This change falls back to the session's normal priority provider when role
resolution returns cleanly empty, logs a warning naming both the role that
failed to resolve and the provider actually substituted, then fires naming
once per session (subsequent calls drop to DEBUG).

This deliberately narrows PR #300 (fix(hooks): session-naming abort on
role-resolution failure, not silent downgrade) and does not undo it:

  - Resolver raises an exception → still aborts. Unchanged. An exception is
    an unknown, possibly transient failure; falling back could route onto the
    expensive model on every retry — the cost leak #300 guarded against.
  - Resolver returns cleanly empty → now falls back loudly. This is a
    deterministic config gap. Aborting means the feature never runs; falling
    back means it at least tries and admits what it did.

Related: This silent skip confounded a platform A/B test. The Linux run showed
zero errors not because the defect was absent, but because naming had silently
skipped and never exercised the provider code path. The Windows run had a fast
candidate, ran naming, and surfaced a real provider-lifecycle defect (PR #93).

Out of scope: If resolved is non-empty but no entry in providers matches the
resolved name, the loop falls through to the generic fallback with no warning
at all — a related silent gap left for follow-up.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@bkrabach
Brian Krabach (bkrabach) marked this pull request as ready for review August 18, 2026 02:03
@sadlilas
Salil Das (sadlilas) merged commit 3f9a6e2 into main Aug 18, 2026
4 checks passed
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.

3 participants