Context
The @gittensory mention-command parser (src/github/commands.ts) only recognizes a fixed, literal
verb alphabet — a comment that doesn't use exact known syntax gets zero response, even a plain-English
question addressed at the bot. This was surfaced directly: a contributor wrote "Could you re-run the
Gittensory review / reopen?" on a PR and the bot never replied, because the comment never contained the
literal @gittensory substring the parser requires (a separate, correct-behavior finding — not a bug).
There is already a read-only Q&A command catalog (GITTENSORY_MENTION_COMMAND_CATALOG,
commands.ts:28-53), structurally isolated from the write-capable action catalog
(GITTENSORY_ACTION_COMMAND_CATALOG, commands.ts:65-106) — isGittensoryActionCommand()
(commands.ts:312-314) is checked before the Q&A dispatcher ever runs, so anything placed in the Q&A
catalog structurally cannot reach a write handler (review/pause/resume/gate-override/etc.)
through the normal dispatch path. This is the foundation a new capability builds on.
@gittensory ask <question> already captures free text (commands.ts:271) but — this is the key gap —
answers it with deterministic decision-pack data, not real LLM generation. The only LLM-generated
text anywhere in that path is a private, never-posted summary (attachPrivateAiSummary →
summarizeAgentBundleWithAi). There is no existing surface where a contributor's free-text question gets
a genuinely LLM-generated, grounded answer.
Separately, this codebase already has a proven, config-driven pattern for routing specific AI
capabilities to a local Ollama instance instead of the frontier model chain:
advisoryAiRouting (src/types.ts:1230-1240, src/review/advisory-ai-routing-config.ts) currently
gates 4 capabilities (slop, e2eTestGen, planner, summaries) through one swap function,
withAdvisoryAiEnv() (src/selfhost/ai.ts:1309-1311) — global env var (AI_ADVISORY_BASE_URL etc.,
wired at src/server.ts:511-532) decides whether local inference exists at all; a per-repo
.gittensory.yml boolean decides whether a given capability is allowed to use it. Adding a 5th
capability is "wire one more flag," not a new integration.
Goal
Give contributors and maintainers a way to @gittensory a real question and get a grounded,
LLM-generated answer — explicitly scoped down for v1: read-only, cannot retrigger reviews, change
gate state, or perform any existing write-action command. Config-driven throughout so any self-hoster
running their own instance for their own repos can enable/scope this for themselves, not something
hardcoded to this maintainer's 3 repos.
Sub-issues
Both were scored against a 3rd option (fully open-ended conversational Q&A) which was explicitly
rejected for v1: it requires unproven num_ctx/model-quality tuning (no existing advisory call site
sets a context-window override) and a materially larger prompt-injection/output-safety surface — real
work, not just wiring, and not worth the risk until v1 usage data exists.
Known gaps surfaced during research (track separately, not blocking either sub-issue)
commandRateLimitPolicy and reviewNagPolicy both default to "off" fleet-wide — a self-hoster
who enables a new AI-cost-bearing command without separately opting into rate limiting gets no
invocation ceiling at all. Both sub-issues below should either require commandRateLimitPolicy !== "off" as a documented co-requisite, or this should become its own follow-up issue to change the
default posture.
- Doc/code drift:
docker-compose.yml:336 tells self-host operators to ollama pull llama3.2, but the
code's hardcoded fallback model (DEFAULT_OLLAMA_CHAT_MODEL, src/selfhost/ai.ts:148) is llama3.1.
A self-hoster who only pulls what the compose comment says gets a 404 unless they also pull llama3.1
or set OLLAMA_AI_MODEL explicitly.
Key files
src/github/commands.ts — catalogs, parser, AI_COST_BEARING_COMMANDS, sanitizers
(neutralizePublicMarkdownText/sanitizePublicComment), ask's render path as template
src/settings/command-authorization.ts — per-command, per-repo-overridable authorization policy
src/queue/processors.ts — maybeProcessGittensoryMentionCommand (14335), maybeThrottleGittensoryCommand
(14238-14333), buildMentionCommandBundle (14696-14735)
src/review/advisory-ai-routing-config.ts, src/types.ts:1230-1240 — capability-flag pattern to extend
(+ packages/gittensory-engine twin)
src/selfhost/ai.ts:1300-1311 — withAdvisoryAiEnv
src/services/ai-summaries.ts — generation-layer template (budget gate, sanitizer, guaranteed-safe fallback)
src/signals/focus-manifest.ts:490-590 — yml > DB > default merge to mirror
Effort
Maintainer-only, roadmap. Research/design pass already complete (this issue captures its findings); no
code written yet.
Context
The
@gittensorymention-command parser (src/github/commands.ts) only recognizes a fixed, literalverb alphabet — a comment that doesn't use exact known syntax gets zero response, even a plain-English
question addressed at the bot. This was surfaced directly: a contributor wrote "Could you re-run the
Gittensory review / reopen?" on a PR and the bot never replied, because the comment never contained the
literal
@gittensorysubstring the parser requires (a separate, correct-behavior finding — not a bug).There is already a read-only Q&A command catalog (
GITTENSORY_MENTION_COMMAND_CATALOG,commands.ts:28-53), structurally isolated from the write-capable action catalog(
GITTENSORY_ACTION_COMMAND_CATALOG,commands.ts:65-106) —isGittensoryActionCommand()(
commands.ts:312-314) is checked before the Q&A dispatcher ever runs, so anything placed in the Q&Acatalog structurally cannot reach a write handler (
review/pause/resume/gate-override/etc.)through the normal dispatch path. This is the foundation a new capability builds on.
@gittensory ask <question>already captures free text (commands.ts:271) but — this is the key gap —answers it with deterministic decision-pack data, not real LLM generation. The only LLM-generated
text anywhere in that path is a private, never-posted summary (
attachPrivateAiSummary→summarizeAgentBundleWithAi). There is no existing surface where a contributor's free-text question getsa genuinely LLM-generated, grounded answer.
Separately, this codebase already has a proven, config-driven pattern for routing specific AI
capabilities to a local Ollama instance instead of the frontier model chain:
advisoryAiRouting(src/types.ts:1230-1240,src/review/advisory-ai-routing-config.ts) currentlygates 4 capabilities (
slop,e2eTestGen,planner,summaries) through one swap function,withAdvisoryAiEnv()(src/selfhost/ai.ts:1309-1311) — global env var (AI_ADVISORY_BASE_URLetc.,wired at
src/server.ts:511-532) decides whether local inference exists at all; a per-repo.gittensory.ymlboolean decides whether a given capability is allowed to use it. Adding a 5thcapability is "wire one more flag," not a new integration.
Goal
Give contributors and maintainers a way to
@gittensorya real question and get a grounded,LLM-generated answer — explicitly scoped down for v1: read-only, cannot retrigger reviews, change
gate state, or perform any existing write-action command. Config-driven throughout so any self-hoster
running their own instance for their own repos can enable/scope this for themselves, not something
hardcoded to this maintainer's 3 repos.
Sub-issues
@gittensory chat <question>: grounded LLM Q&A via local Ollama (see linked issue)@gittensorymentions (see linked issue)Both were scored against a 3rd option (fully open-ended conversational Q&A) which was explicitly
rejected for v1: it requires unproven
num_ctx/model-quality tuning (no existing advisory call sitesets a context-window override) and a materially larger prompt-injection/output-safety surface — real
work, not just wiring, and not worth the risk until v1 usage data exists.
Known gaps surfaced during research (track separately, not blocking either sub-issue)
commandRateLimitPolicyandreviewNagPolicyboth default to"off"fleet-wide — a self-hosterwho enables a new AI-cost-bearing command without separately opting into rate limiting gets no
invocation ceiling at all. Both sub-issues below should either require
commandRateLimitPolicy !== "off"as a documented co-requisite, or this should become its own follow-up issue to change thedefault posture.
docker-compose.yml:336tells self-host operators toollama pull llama3.2, but thecode's hardcoded fallback model (
DEFAULT_OLLAMA_CHAT_MODEL,src/selfhost/ai.ts:148) isllama3.1.A self-hoster who only pulls what the compose comment says gets a 404 unless they also pull
llama3.1or set
OLLAMA_AI_MODELexplicitly.Key files
src/github/commands.ts— catalogs, parser,AI_COST_BEARING_COMMANDS, sanitizers(
neutralizePublicMarkdownText/sanitizePublicComment),ask's render path as templatesrc/settings/command-authorization.ts— per-command, per-repo-overridable authorization policysrc/queue/processors.ts—maybeProcessGittensoryMentionCommand(14335),maybeThrottleGittensoryCommand(14238-14333),
buildMentionCommandBundle(14696-14735)src/review/advisory-ai-routing-config.ts,src/types.ts:1230-1240— capability-flag pattern to extend(+
packages/gittensory-enginetwin)src/selfhost/ai.ts:1300-1311—withAdvisoryAiEnvsrc/services/ai-summaries.ts— generation-layer template (budget gate, sanitizer, guaranteed-safe fallback)src/signals/focus-manifest.ts:490-590— yml > DB > default merge to mirrorEffort
Maintainer-only, roadmap. Research/design pass already complete (this issue captures its findings); no
code written yet.