You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #4594 (Option 3 — near-zero-risk fast-follow to #4595).
Context
Today, an @gittensory mention whose verb token doesn't resolve to a known command is silently
downgraded to { name: "help", unknownVerb: rawVerbToken } (src/github/commands.ts:278), which
triggers a fuzzy "did-you-mean" hint (buildDidYouMeanSections, commands.ts:766). This closes the
literal "contributor doesn't know the exact command syntax" gap without the larger safety surface
of open-ended generation (#4594's rejected Option 2): the classifier only ever picks a label from a
closed, pre-enumerated set — it never generates a new factual claim, so there is no hallucination surface
to defend against, only mis-routing (annoying, not misleading or unsafe).
Requirements
Trigger: same detection surface as the existing unrecognized-verb fallback — an @gittensory
mention with an unrecognized verb (or no verb) plus non-trivial trailing free text, when the new
capability flag is enabled.
Closed-set classifier, not a generator: maps free text to the single closest match among the existing Q&A commands only (preflight, blockers, duplicate-check, next-action, reviewability, repo-fit, packet, ask, and — once feat(commands): add @gittensory chat <question> — grounded LLM Q&A via local Ollama #4595 ships — chat) or returns "no match."
On a match, dispatch through the exact samebuildMentionCommandBundle path those commands already
use (processors.ts:14696-14735) — the answer content is 100% pre-existing deterministic output, only
reachable without knowing the exact verb. On no-match, fall back to the existing buildDidYouMeanSections hint unchanged.
Hard runtime allowlist, not prompt-instructed containment: the classifier's output type is a
literal union of the Q&A catalog's command names — never action-catalog names. Any output outside
that allowlist (including a prompt-injection attempt to make the classifier "choose" review/pause/gate-override/etc.) must be rejected by a hard runtime check before dispatch, not
relied on the prompt to refuse. This must be exhaustively testable: feed the classifier adversarial
inputs and assert its raw output is filtered to the closed Q&A-catalog-name set in 100% of cases —
this is a much smaller, fully enumerable test surface than filtering free-form prose.
Rate-limit tier: the classifier call is cheap (short prompt, tiny closed-set output) — still add it
to AI_COST_BEARING_COMMANDS (commands.ts:321-330) anyway for budget-ledger consistency, since it
still calls the AI binding, even though its cost profile is much smaller than feat(commands): add @gittensory chat <question> — grounded LLM Q&A via local Ollama #4595's generation call.
Show the interpretation: post the matched command name alongside the answer (e.g. "interpreted your
question as @gittensory blockers") so a wrong match is immediately visible/correctable. Keep a
"no confident match" threshold that prefers the existing did-you-mean fallback over a low-confidence
guess.
Deliverables
Small classifier function (short prompt + closed JSON output schema)
Hard allowlist-enforcement check (output filtered to Q&A-catalog names only, tested exhaustively)
Wiring into the existing unrecognized-verb branch of the parser/dispatcher
(buildDidYouMeanSections's call site, commands.ts:766)
AI_COST_BEARING_COMMANDS membership
"Interpreted as" prefix on the routed answer card
Unit tests: classifier allowlist enforcement (adversarial-input corpus), routing accuracy on a
sample question set, fallback-to-did-you-mean on no-match, 99% patch coverage per house rules
A contributor who @gittensorys a question using natural language instead of the exact command syntax
(e.g. "why is this stuck" instead of @gittensory blockers) gets routed to the correct existing answer
automatically, with the interpretation shown so a wrong guess is obviously correctable — zero new
generated content, zero new injection surface, entirely reusing existing, already-tested answer
rendering. Config-driven so any self-hoster can enable/scope it independently of #4595.
Part of #4594 (Option 3 — near-zero-risk fast-follow to #4595).
Context
Today, an
@gittensorymention whose verb token doesn't resolve to a known command is silentlydowngraded to
{ name: "help", unknownVerb: rawVerbToken }(src/github/commands.ts:278), whichtriggers a fuzzy "did-you-mean" hint (
buildDidYouMeanSections,commands.ts:766). This closes theliteral "contributor doesn't know the exact command syntax" gap without the larger safety surface
of open-ended generation (#4594's rejected Option 2): the classifier only ever picks a label from a
closed, pre-enumerated set — it never generates a new factual claim, so there is no hallucination surface
to defend against, only mis-routing (annoying, not misleading or unsafe).
Requirements
@gittensorymention with an unrecognized verb (or no verb) plus non-trivial trailing free text, when the new
capability flag is enabled.
existing Q&A commands only (
preflight,blockers,duplicate-check,next-action,reviewability,repo-fit,packet,ask, and — once feat(commands): add @gittensory chat <question> — grounded LLM Q&A via local Ollama #4595 ships —chat) or returns "no match."On a match, dispatch through the exact same
buildMentionCommandBundlepath those commands alreadyuse (
processors.ts:14696-14735) — the answer content is 100% pre-existing deterministic output, onlyreachable without knowing the exact verb. On no-match, fall back to the existing
buildDidYouMeanSectionshint unchanged.literal union of the Q&A catalog's command names — never action-catalog names. Any output outside
that allowlist (including a prompt-injection attempt to make the classifier "choose"
review/pause/gate-override/etc.) must be rejected by a hard runtime check before dispatch, notrelied on the prompt to refuse. This must be exhaustively testable: feed the classifier adversarial
inputs and assert its raw output is filtered to the closed Q&A-catalog-name set in 100% of cases —
this is a much smaller, fully enumerable test surface than filtering free-form prose.
advisoryAiRouting.intentRouting: boolean(defaultfalse) — same shape asfeat(commands): add @gittensory chat <question> — grounded LLM Q&A via local Ollama #4595's
chatQaflag (type + normalizer + engine-package twin + focus-manifest merge). Sameno-frontier-fallback divergence as feat(commands): add @gittensory chat <question> — grounded LLM Q&A via local Ollama #4595: never falls back to the frontier chain; decline/no-op
(silently fall through to the existing did-you-mean hint) if the flag is off or
env.AI_ADVISORYisunconfigured.
to
AI_COST_BEARING_COMMANDS(commands.ts:321-330) anyway for budget-ledger consistency, since itstill calls the AI binding, even though its cost profile is much smaller than feat(commands): add @gittensory chat <question> — grounded LLM Q&A via local Ollama #4595's generation call.
question as
@gittensory blockers") so a wrong match is immediately visible/correctable. Keep a"no confident match" threshold that prefers the existing did-you-mean fallback over a low-confidence
guess.
Deliverables
intentRoutingcapability flag: type + normalizer + engine-package twin + focus-manifest merge(
buildDidYouMeanSections's call site,commands.ts:766)AI_COST_BEARING_COMMANDSmembershipsample question set, fallback-to-did-you-mean on no-match, 99% patch coverage per house rules
config/examples/gittensory.full.ymldocumentationExpected outcome
A contributor who
@gittensorys a question using natural language instead of the exact command syntax(e.g. "why is this stuck" instead of
@gittensory blockers) gets routed to the correct existing answerautomatically, with the interpretation shown so a wrong guess is obviously correctable — zero new
generated content, zero new injection surface, entirely reusing existing, already-tested answer
rendering. Config-driven so any self-hoster can enable/scope it independently of #4595.
Links + resources
parseGittensoryMentionCommand(commands.ts:244-279),buildDidYouMeanSections(commands.ts:766)advisoryAiRoutingpattern:src/types.ts:1230-1240,src/review/advisory-ai-routing-config.tssrc/queue/processors.ts:14335-14735