Skip to content

[P2] lesson-feed reads OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL, not the DISPATCH_LLM_* vars the groomer uses #913

Description

@itsmiso-ai

Ask: Make src/lib/lesson-feed.ts read DISPATCH_LLM_API_KEY / DISPATCH_LLM_BASE_URL and a DISPATCH_LESSON_FEED_MODEL env var (with OPENAI_* as documented legacy fallback), and update .env.example accordingly so the lesson feed actually fires in deployments that only configure DISPATCH_LLM_*.

Expected files: src/lib/lesson-feed.ts, .env.example, docs/*.md (only files mentioning OPENAI_API_KEY for the lesson feed)

Problem: The hosted groomer config (src/lib/groomer/config.ts) and the LLM lesson feed (src/lib/lesson-feed.ts) read different env vars for the same thing. The groomer uses DISPATCH_LLM_API_KEY and DISPATCH_LLM_BASE_URL; the lesson feed uses OPENAI_API_KEY and OPENAI_BASE_URL (.env.example explicitly calls OPENAI_* the "Legacy / lesson-feed fallback"). In a deployment that only sets DISPATCH_LLM_* (which is what every recent runbook and the .env.example top section push operators toward), the lesson feed silently no-ops — extractLessonFromFixOutcome returns { kind: 'no_lesson' } because apiKey is the empty string and the if (!apiKey) early-return fires. There is no startup warning, no log line, no metric. The lesson-feed trigger that closes the loop from pr-fix/tombstone outcomes back into AGENTS.md (introduced for issue #754 / windowstead#321-style "assert_eq is 2-arg" lessons) is therefore dead in any non-OpenAI deployment, and no one would notice until they checked the lesson-feed trigger logs.

Evidence:

  • src/lib/lesson-feed.ts:78–80 reads OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL. The only dispatch-namespaced env var the file reads is none.
  • src/lib/groomer/config.ts:67–68 reads DISPATCH_LLM_BASE_URL and DISPATCH_LLM_API_KEY exclusively — there is no OPENAI_* fallback path there.
  • .env.example lines 159–171 document OPENAI_* as the lesson-feed fallback and never mention DISPATCH_LLM_* for the lesson feed.
  • src/lib/pr-fix-queue.ts:249–253 swallows lesson-feed errors with .catch(() => {}), so a missing API key is invisible at runtime.
  • The silent-fallback pattern is what AGENTS.md calls a "completed but useless" outcome — the lifecycle succeeds, the lesson never lands.

Acceptance: src/lib/lesson-feed.ts reads DISPATCH_LLM_API_KEY (with OPENAI_API_KEY as documented fallback), DISPATCH_LLM_BASE_URL (with OPENAI_BASE_URL as documented fallback), and either DISPATCH_LESSON_FEED_MODEL or DISPATCH_GROOMER_MODEL (with OPENAI_MODEL as documented fallback). .env.example is updated to mark OPENAI_* as the lesson-feed legacy fallback and to point operators at DISPATCH_LLM_* first. A test in src/lib/lesson-feed.test.ts pins the precedence (DISPATCH_* > OPENAI_) and the missing-key early-return. A startup log line or one-time warning fires when OPENAI_ is used while DISPATCH_* is set, so the legacy fallback path is observable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions