fix: slash dispatch falls back to live skills_discovery on SKILL_SHORTCUTS miss - #290
Conversation
…TCUTS miss SKILL_SHORTCUTS is populated once at CommandProcessor construction and never refreshed, so skills that resolve after startup (@namespace sources resolving on first provider:request; runtime load_skill(source=...) registration) never get slash commands — measured live: 19 shortcuts returned Unknown command forever while /skills and /skill <name> (live capability reads) worked. - Dispatch miss path: re-run _populate_skill_shortcuts() (cheap live read) and re-check once before returning unknown_command. - /help: refresh the cache before rendering so displayed shortcuts match reality (/skills already read live). - Documented the additive-only cache limitation. - 8 new tests; suite 1568 passed, no new pyright errors. Root fix lands separately in amplifier-foundation (eager mention_resolver registration); this is defense-in-depth that also covers runtime skill registration, which the root fix doesn't. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Merge-queue verification — PASS, merging with
|
| Gate | Method | Result |
|---|---|---|
| Diff scoped to the title | git diff 963d793 pr-290 --stat → only amplifier_app_cli/main.py (+41/-7) and one new test file |
PASS |
| Fail-before: new tests fail on pre-fix source | Reverted only main.py to 963d793, kept the new test file → 5 failed, 3 passed. The 5 failures are real behavioral assertions ('unknown_command' == 'load_skill', "simplify" in CommandProcessor.SKILL_SHORTCUTS → {}, /wayfinder-pack missing from rendered /help text) — not import/collection errors. The 3 passes are the negative controls (genuinely-unknown command still unknown; fail-soft with no discovery capability) which correctly hold on both old and new code |
PASS |
| Pass-after | Restored main.py to PR state → 8/8 passed |
PASS |
| Full suite green | uv run pytest -q → 1568 passed, 1 skipped, 13 deselected, 1 xfailed (matches PR's claimed count exactly) |
PASS |
| Lint clean | ruff check amplifier_app_cli/main.py tests/test_skill_shortcuts_live_fallback.py → clean |
PASS |
| No new type errors | pyright amplifier_app_cli/main.py → 45 errors both before (963d793) and after (pr-290) — identical count, none introduced (all pre-existing RustCoordinator/PROMPT_COMPLETE attr-access issues unrelated to this diff) |
PASS |
| CI (all legs) | gh pr checks 290 → ubuntu×2, macos×2, windows×2, integration×2, license/cla — all pass |
PASS |
| Default behavior otherwise unchanged | The fallback path only fires on a SKILL_SHORTCUTS miss (_populate_skill_shortcuts() re-run + one recheck); an already-hit shortcut takes the exact same first branch as before (factored into _dispatch_skill_shortcut, called identically from both sites, verified by reading the diff — no logic changed for the hit path, just extracted into a closure). _populate_skill_shortcuts remains additive-only (.update()), documented as such in the new docstring |
PASS |
| No unvalidated performance claim | PR states "measured live: 19 shortcuts... returned Unknown command forever" as motivation/background, not as a number this verification re-measured; no new performance claim made | PASS — honest |
Relationship to the companion foundation fix: PR body correctly identifies the root cause as foundation's late mention_resolver registration (fixed in microsoft/amplifier-foundation#347, merged earlier in this same pass) and frames this PR as deliberate defense-in-depth covering runtime skill registration (load_skill(source=...)), which the root fix does not reach. Both fixes are independently sound and independently mergeable; neither depends on the other landing first.
Concurrency check: main moved from 963d793 to 8c4ad7a (#292 resume role-threading, #293 routing-shadow marking, #294 routing last-write-wins fix) during this verification pass — none overlap this PR's files (confirmed above); no rebase needed before merge.
All gates pass. Merging via gh pr merge --squash --admin (required-review ruleset bypass disclosed here — I am the PR author and no other human reviewer is available in this workflow).
Problem
SKILL_SHORTCUTSis populated once inCommandProcessor.__init__and dispatch reads only that frozen dict. Skills that appear after startup —@namespace:skillssources resolving on the first provider request, or runtimeload_skill(source=…)registration — never get slash commands. Measured live: 19 shortcuts (wayfinder-pack, design-council family, …) returned Unknown command forever, while/skillsand/skill <name>(live capability reads) worked after one prompt./helpand/skillsvisibly disagreed.Fix
_populate_skill_shortcuts()(a cheap read off the liveskills_discoverycapability) and re-check once before returningunknown_command. Fail-soft preserved when no discovery capability exists./help: refresh the cache before rendering the shortcuts section (/skillsalready read live — unchanged)._populate_skill_shortcuts.Validation
tests/test_skill_shortcuts_live_fallback.py): late-appearing skill dispatches (with args + alias mapping), genuinely unknown commands still fail, fail-soft without the capability,/helpreflects post-construction skills. Suite: 1568 passed, no new pyright errors (pre-existing count identical, verified via stash)./wayfinder-packdispatches; cold/helpcomplete. Host baseline red on all three.Relationship to the root fix
The root cause is foundation registering
mention_resolveraftersession.initialize()— fixed in microsoft/amplifier-foundation#347. This PR is deliberate defense-in-depth: it additionally covers runtime skill registration, which eager mount-time resolution cannot.Known follow-up (flagged, not fixed here)
session_spawner.pyregistersmention_resolverafterchild_session.initialize()in two functions (spawn + resume paths) — the same late-registration bug class in the CLI's own spawn implementation. Sub-agent sessions get late skill-source resolution as a result. Worth a small follow-up PR mirroring the foundation fix.🤖 Generated with Amplifier
Co-Authored-By: Amplifier 240397093+microsoft-amplifier@users.noreply.github.com