feat(auq): prose fallback when AskUserQuestion fails (interactive sessions)

On a genuine AUQ failure (tool absent, or present-but-erroring like Conductor's
flaky MCP returning '[Tool result missing due to internal error]'): retry once,
then branch on SESSION_KIND — spawned auto-chooses, headless BLOCKs, interactive
renders a prose decision brief the user answers by typing a letter.

The prose fallback MUST surface the triad: a clear ELI10 of the issue, a
per-choice Completeness score, and a recommendation+why (one paragraph per
choice). Carves out the [plan-tune auto-decide] denial as NOT a failure, and
qualifies the former 'tool_use, not prose' assertions so the rule isn't
self-contradicting. Tests pin the triad, the SESSION_KIND branch, the OV2
collision guard, the always-loaded guarantee, and a cross-file invariant on the
auto-decide prefix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-06-07 17:51:22 -07:00
parent 28d75fe9f2
commit c475d73b34
4 changed files with 116 additions and 4 deletions
+5
View File
@@ -47,6 +47,11 @@ const MANDATORY: Array<{ name: string; re: RegExp }> = [
{ name: 'Completeness coverage rule', re: /Completeness\s*:/i },
{ name: 'kind-vs-coverage rule', re: /options differ in kind/i },
{ name: 'Self-check checklist', re: /Self-check before emitting/i },
// The runtime-failure fallback must be ALWAYS-LOADED too: when an AUQ call errors
// mid-skill, the model needs the prose-fallback rule in context that instant, not
// stranded in an on-demand section. Same guarantee as the format spec above.
{ name: 'AUQ-failure fallback subsection', re: /When AskUserQuestion is unavailable or a call fails/i },
{ name: 'fallback SESSION_KIND branch', re: /SESSION_KIND/ },
];
/** Per-skill AUQ rules that govern review-finding cadence. A carve may move