Skip to content

feat(action): named models per comment trigger and provider credential docs (plan 125) - #37

Merged
pkieltyka merged 3 commits into
masterfrom
plan-125-model-aliases
Sep 25, 2026
Merged

pkieltyka merged 3 commits into
masterfrom
plan-125-model-aliases

Conversation

@pkieltyka

@pkieltyka pkieltyka commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Implements plan 125.

What changes

Named models, picked per comment

- uses: 0xPolygon/codegenie@<next tag>
  env:
    OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
  with:
    model: luna            # default: automatic reviews + bare "codegenie review"
    models: |
      luna:     openrouter/openai/gpt-6-luna:xhigh
      deepseek: openrouter/deepseek/deepseek-v4.1-flash:max
      opus:     anthropic/claude-opus-5:high
  • codegenie review opus runs one review with the opus entry. The first word on the trigger phrase's line is looked up in the workflow's list, and nothing else in the comment is read: no model specs, reasoning levels or flags from comment text.
  • The lookup runs only after the live write-permission check. An unlisted name gets a fixed reply listing the configured aliases, and no review runs. Unauthorized commenters get no reply.
  • Without models, behavior is unchanged, including trailing comment text being ignored. A regression test pins the simple model + llm-api-key form.

llm-api-key is the only key when set

  • It clears the provider's competing credential vars (including ANTHROPIC_AUTH_TOKEN) and overrides native env vars. This reverses the previous precedence: a workflow that sets both, with different values, now uses llm-api-key.
  • All configured models must share its provider; otherwise the run fails with a clear config error.
  • pi-ai lets a stored login own its provider ahead of env vars. So on a self-hosted runner with a stored codegenie provider login for that provider, the Action refuses to run instead of silently ignoring llm-api-key. The CLI is unchanged.

Clearer model errors

  • The resolver now keeps its failure reason: unknown model, deprecated model, missing credentials (naming the env var to set), or the unchanged generic message for anything unattributable. All keep config_error.
  • The Action shows only these messages in the failure comment, scrubbed and capped. The failure comment is now sanitized as a whole; before, provider messages reached the PR without the mention/HTML sanitizer.

Credentials docs

  • The provider→env-var table is synced with pi-ai 0.87.1 (qwen-token-plan*, baseten, meta, radius were missing), with a registry coverage test that fails when a provider is added upstream without a mapping.
  • models.md gains a generated Credentials table. Most of its diff is regeneration catching up with the installed registry (1103 → 1490 models); only the Credentials section is new logic.
  • The README documents the aliases, credentials, precedence change and caveats. A mistyped alias still cancels an in-flight review, and inline comments accumulate across models.
  • The two example workflows are merged into examples/workflows/codegenie-review.yml, which serves both triggers with the same trust model as the dogfood workflow.

Review

An independent adversarial review found three issues: the stored-login bypass (fixed by the owner-chosen guard), a nonexistent provider labeled "missing credentials", and numeric alias names being rejected. All three are fixed with tests. It found the trust boundary, secret handling on every published surface, backward compatibility and error labeling sound. Mutation checks confirm the sanitizer and credential-clearing tests fail when those fixes are removed.

Validation

  • pnpm test: 1,583 tests across 69 files, including actionlint on the merged example.
  • make evals: 39 passed.
  • Typecheck, build and git diff --check pass; models.md regenerates identically.
  • The built CLI prints the missing-credentials, unknown-model and deprecated-model messages on a real commit range, before any model call.

Not done yet

  • Dogfood on a test PR: a bare trigger, an alias, an unknown alias, and an alias with a missing key.
  • Release: the package is bumped to 0.7.0 and the examples and README pin @v0.7.0 (the first release with the models input). Publish npm before pushing the v0.7.0 tag.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NxBabX2aBd6eRLJryVci78

…l docs (plan 125)

Adds a `models` Action input: a flat `alias: provider/model[:reasoning]`
list. `model` stays the default (an alias or a full spec) for automatic
reviews and a bare trigger; `codegenie review <alias>` runs one review
with a listed model. The alias is a closed-set lookup resolved only after
the live permission check; an unlisted name gets a fixed reply and no
review. Without `models`, behavior is unchanged.

`llm-api-key`, when set, is now the only model key: it clears competing
credential env vars for its provider and overrides native vars, all
configured models must share one provider, and the Action refuses to run
when a stored login on a self-hosted runner would override it.

Model resolution failures now say unknown model, deprecated model, or
missing credentials (naming the env var) instead of one generic message;
the Action shows these in the failure comment, which is now sanitized.

Syncs the provider env-var table with pi-ai 0.87.1 (qwen-token-plan*,
baseten, meta, radius), adds a registry coverage test, generates a
Credentials table in models.md (also catching up the stale registry
listing), merges the example workflows into one, and updates the README.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxBabX2aBd6eRLJryVci78
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🧞 Codegenie Review

Warning

Review completed with unresolved questions. 9 question(s) remain unresolved; absence of a confirmed finding does not establish safety.

0 confirmed findings retained from completed work. Unresolved questions require attention.

Coverage

Reviewed 55/99 hunks.
Excluded by configuration/planning: 44 hunks.
Coverage levels: deep 41, normal 11, light 3, skip 44.

  • models.md: generated file
  • scripts/write-models-md.mjs: generated file
  • specs/plans/125-issue-125-github-model-aliases-and-provider-credentials.md: configured skip rule
  • specs/plans/README.md: configured skip rule

🙋 Needs Human Attention

  • Is the stricter README line 145 wording (models spanning several providers always fail with llm-api-key set) intended as written, or should the documentation be updated to mention the shared-env-var case in which provider pairs such as moonshotai/moonshotai-cn are accepted?; Should the llm-api-key input description in action.yml be relaxed so that it states the implemented single-shared-API-key-env-var rule rather than requiring model plus every alias to use one provider?; Do any remaining tests or exports reference the removed entrypoint symbols applyGenericApiKey/parseModelSpec directly rather than the new ./models.js re-exports?; Can a comment-supplied token (rather than a workflow models entry) ever reach llmConfig.model so that modelResolutionMessage echoes comment-controlled text into the published failure comment via modelResolutionFromError?; Does pi-ai's google-vertex provider prefer ADC / GOOGLE_APPLICATION_CREDENTIALS / GOOGLE_CLOUD_PROJECT over GOOGLE_CLOUD_API_KEY, such that an explicitly routed llm-api-key would be ignored despite the 'Clearing these leaves only an explicitly routed key' comment?; Do the entrypoint-level executeGitHubActionCommand tests assert that LLM_API_KEY is expanded into the selected provider's native env var for the alias-selected model (not just the default model)?; Does an entrypoint-level test prove that an unknown comment token short-circuits the run (posts renderUnknownAliasReply and does not execute a review), rather than only the unit-level selectModel/renderUnknownAliasReply assertions added here?; Does the test at tests/github-action.test.ts:1250 enshrine the not-a-provider/x → "does not accept an API key" behavior, and does parseModelAliases reject unknown providers with the clearer "names unknown provider" message, such that a typo'd provider in model surfaces a misleading credential error relative to the alias path?; Does the entrypoint (or any test) pin that applyLlmApiKey's clearing of competing provider credential env vars happens for the selected providers before runReview, i.e. is the delete-then-set behavior exercised at the entrypoint boundary and not only in the models.ts unit tests?; Should the example-workflow test derive the expected step env credential var names from the parsed models aliases (e.g. via getPiApiKeyEnvVarName) instead of hardcoding ["OPENROUTER_API_KEY","ANTHROPIC_API_KEY"], so adding an alias with a new provider to examples/workflows/codegenie-review.yml cannot ship an example that lacks that provider's key?

    • Files: README.md, action.yml, examples/workflows/codegenie-review.yml, src/github-action/entrypoint.ts, src/github-action/models.ts, src/llm/pi-runner.ts
    • Symbols: applyGenericApiKey, applyLlmApiKey, boundedPublishedText, executeGitHubActionCommand, getPiApiKeyEnvVarName, getPiCredentialEnvVarNames
    • Reason: Packet reviewer could not resolve this question from the reviewed context. Grouped from 10 related hints across 10 packets.
  • Do decision/lifecycle record assertions in the GitHub Action tests pin the new modelAlias/modelSpec fields for the run:true and unknown-alias paths (including the no-model-configured case where both fields are omitted)?; Is it intended that, once models is configured, a natural-language comment such as "codegenie review please look at auth" resolves the token "please" to unknown_alias and skips the review with a reply instead of running the default model?; With models configured, any extra prose token on the trigger line (e.g. "codegenie review please focus on auth") resolves to unknown_alias and skips the review with a reply instead of running the default model — is that the intended plan-125 contract rather than a usability regression?

    • Files: specs/plans/125-issue-125-github-model-aliases-and-provider-credentials.md, src/github-action/entrypoint.ts, src/github-action/event-gate.ts, src/github-action/models.ts
    • Symbols: DecisionRecord, emitActionRecord, modelRecordFields, requestedAliasFromComment, runGithubAction, selectModel
    • Reason: Packet reviewer could not resolve this question from the reviewed context. Grouped from 3 related hints across 3 packets.
  • Is it intended that an invalid models/model configuration throws (red run) for a trigger comment by an actor who would later fail the write-permission check, since resolveModelConfig at entrypoint.ts:123 runs before hasWritePermission?; Is posting the unknown-alias reply before the inputs.preflightOnly early return intended for the two-job preflight setup (preflight posts the reply, review job is gated off by should-run=false)?

    • Files: README.md, action.yml, src/github-action/entrypoint.ts, src/github-action/models.ts
    • Symbols: executeGitHubActionCommand, hasWritePermission, renderUnknownAliasReply, resolveModelConfig
    • Reason: Packet reviewer could not resolve this question from the reviewed context. Grouped from 2 related hints across 2 packets.
  • parseDocument (not parseAllDocuments) is used for the models input, so a multi-document YAML value (--- separated) would silently drop later documents' aliases instead of erroring; is that reachable/acceptable for the Action input?; Should models alias entries accept the CLI-only provider aliases (codex, copilot, bedrock, vertex, gemini) as provider prefixes, e.g. luna: gemini/gemini-2.5-pro? Today parseModelAliases rejects them because providerKnown does not apply resolveProviderAlias.

    • Files: src/github-action/models.ts, src/provider/provider-services.ts
    • Symbols: PROVIDER_ALIASES, parseModelAliases, providerKnown, resolveProviderAlias
    • Reason: Packet reviewer could not resolve this question from the reviewed context. Grouped from 2 related hints across 2 packets.
  • Should the failure branch route through capTerminalBody, given that it currently relies on the entrypoint's PROVIDER_MESSAGE_MAX_CHARS=300 and short diagnostics to stay under ISSUE_COMMENT_MAX_CHARS?

    • Files: src/github-action/entrypoint.ts, src/github-action/render.ts, src/github-action/status-comment.ts
    • Symbols: capTerminalBody, finalizeFailure, renderFailureBody
    • Reason: Packet reviewer could not resolve this question from the reviewed context.

Additional unresolved notes suppressed: 4.

Stats

  • 🤖 Model: anthropic claude-opus-5 high
  • 🧞 Codegenie: v0.6.3 (8cbe1ce9ff)
  • Elapsed time: 6m 43s
  • Git: 0xPolygon/codegenie from master to plan-125-model-aliases (19505c0613)
  • Review completeness: complete.
  • Usage: model calls 114, tokens 3291136, cost $8.7506.
  • Effective caps: tokens 8000000.
  • Local context pressure: 11 degraded tool results, 10 degraded hunks, 4 unresolved notes suppressed.

No confirmed findings

No confirmed findings were retained. The limitations above prevent a clean conclusion.

— View Workflow Job

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧞 Codegenie Review

Warning

Review completed with unresolved questions. 10 question(s) remain unresolved; absence of a confirmed finding does not establish safety.

1 confirmed finding retained from completed work. Unresolved questions require attention.

Reviewed 55/96 hunks.
Excluded by configuration/planning: 41 hunks.

Coverage disclosure:

  • models.md: generated file
  • scripts/write-models-md.mjs: generated file
  • specs/plans/125-issue-125-github-model-aliases-and-provider-credentials.md: configured skip rule
  • specs/plans/README.md: configured skip rule

🙋 Needs human attention:

  • Does the README 'Grammar' bullet (first word after trigger phrase, case-insensitive lookup, no model spec accepted from comment text) exactly match the comment parsing implementation in src/github-action/models.ts?; With models configured, any trailing word after the trigger phrase (e.g. "codegenie review please look at auth") now resolves to unknown_alias, posting a reply and skipping the review instead of running the default model — confirm this rejection-over-default behavior is the intended plan-125 contract.; With models configured, any authorized comment of the form "codegenie review " (e.g. "codegenie review this PR") now resolves the first token as an alias and skips the run with an unknown-alias reply instead of reviewing. Is this rejection-over-default behavior documented for users upgrading from the pre-plan-125 "trailing text is ignored" contract?; Does tests/github-action.test.ts still cover the credential wiring boundary previously exercised via applyGenericApiKey (env var precedence, provider-specific key selection) now that the import is renamed to applyLlmApiKey?; Are there added tests asserting requestedAliasFromComment behavior (first word on trigger line, unknown alias handling) in this PR?; Is the positive end-to-end path (llm-api-key actually written into the spawned review's env for a single-provider alias set) asserted anywhere, or only the two failure paths at tests/github-action.test.ts:1389 and :1404?; Does any other suite (e.g. a models.ts-level test) assert that the llm-api-key stored-login guard only triggers for the routed provider?
  • Should action.yml's models description state that setting models makes model required, given model's input default is ""?; Does parseModelAliases("") handle the always-present empty --models value (unset action input) without error, returning an empty alias map?; Does parsing models at argv-parse time (before decideTrigger) make every event on a workflow with a malformed models block fail the job, where previously only --model specs were validated there? Confirm this hard-fail-on-all-events posture is intended.; Does yaml's parseDocument silently drop content after a --- document separator in the models input, so aliases listed after such a line are ignored without an error instead of being rejected by parseModelAliases?
  • Does createFileAuthStorage(getCodegeniePaths(undefined, env)).get(provider) tolerate a missing/unreadable auth file on hosted runners without throwing, given the new unconditional call whenever LLM_API_KEY routes to a provider?; Is the stored-login / applyLlmApiKey credential validation intentionally skipped in preflight-only mode (it sits after the inputs.preflightOnly early return at entrypoint.ts:170-186), so misconfigured runners only fail in the main review job?; Do the newly added API_KEY_ENV_VARS entries (baseten→BASETEN_API_KEY, meta→META_API_KEY, radius→RADIUS_API_KEY, qwen-token-plan* →QWEN_TOKEN_PLAN[_CN]_API_KEY) exactly match pi-ai's internal env-api-keys table?
  • Is ModelResolutionDetail.kind written verbatim into the world-readable failure JSON without scrubGitHubSecrets/boundedPublishedText, and should the guard narrow to the known kinds to keep future producers from publishing unbounded/unscrubbed text?; Does any caller or test assert on the previous literal message "no usable LLM model could be resolved..." for cases that now return a specific message (unknown_model/deprecated_model/missing_credentials)?; Is labeling an unknown provider plus model as "unknown model /" (rather than an unknown-provider message) acceptable product wording, given tests/model-resolution.test.ts asserts it explicitly?
  • Does any non-test PiAiAdapter implementation other than createRealPiAiAdapter need explainUnresolvedModel to avoid always reporting the generic unresolved message?; Does PiAiAdapter declare explainUnresolvedModel as optional with return type ModelResolutionFailure, so resolution.failure also type-checks and adapter stubs in tests remain compatible?
  • Additional unresolved notes suppressed: 5

— codegenie v0.6.3 (8cbe1ce9ff) · View Workflow Job

Comment on lines +1420 to +1421
// A stored login for another provider, or no llm-api-key, is unaffected.
const other = await runWithModels(pullRequestPayload(), "pull_request", ["--model", "anthropic/claude-opus-5"], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Impact: The authStorage guard in src/github-action/entrypoint.ts is deliberately provider-scoped: after applyLlmApiKey returns keyProvider, the run is refused only when storage.get(keyProvider) finds a stored codegenie login for that same provider. The second half of the test claims to prove that a stored login for a different provider does not block llm-api-key, but it executes through runWithModels, which injects authStorage: { get: () => undefined }. No stored login exists for any provider in that run, so the provider comparison is never discriminated. If the guard regressed to be provider-agnostic — checking a fixed provider such as storage.get("openrouter"), or any stored credential at all — this case would still pass, and the only other authStorage test (lines 1404-1418) asserts the throwing case, which such a regression also satisfies.

With that regression unguarded, the action would hard-fail with invalid_args before the status comment is claimed on any self-hosted runner holding an unrelated stored codegenie login, blocking all reviews for a valid llm-api-key configuration with no test signalling the break.

Verification and uncertainty: Mutating the guard to storage.get("openrouter") or to a [...].some(...) check over all providers leaves tests at lines 1404-1425 green, because the negative case's stub returns undefined for every provider. The provider-scoped predicate itself is confirmed in src/github-action/entrypoint.ts:178-185; a path-scoped search of the suite found only two authStorage injections (tests/github-action.test.ts:1308 in runWithModels and :1411 with provider === "openrouter" ? stored : undefined), and the guard message appears only at entrypoint.ts:183 and test line 1417, so no other test file covers this branch.

The coverage conclusion is bounded to the inspected revision and to tests/**: it remains unverified whether a non-test consumer, such as an e2e or workflow check outside that path, exercises the provider-scoped branch. That assumption is non-essential — it would add coverage elsewhere without changing the fact that this assertion does not discriminate the guard's scoping.

Suggested test: Add a case that makes the provider comparison live, driven through executeGitHubActionCommand directly rather than runWithModels (whose extra parameter carries only env/comments and offers no authStorage override):

it("allows llm-api-key when the stored login belongs to another provider", async () => {
 // authStorage: { get: (provider) => (provider === "openrouter" ? stored : undefined) }
 // run with ["--model", "anthropic/claude-opus-5"] and LLM_API_KEY="sk-ant-explicit"
 // expect: no throw, env.ANTHROPIC_API_KEY === "sk-ant-explicit", runReview called
});

The injected foreign-provider entry means the case cannot pass vacuously, and a provider-agnostic guard throws invalid_args, failing all three expectations. Keep the existing throwing assertion at lines 1404-1418 unchanged.

Evidence:

tests/github-action.test.ts (source)

    // A stored login for another provider, or no llm-api-key, is unaffected.
    const other = await runWithModels(pullRequestPayload(), "pull_request", ["--model", "anthropic/claude-opus-5"], {
      env: { LLM_API_KEY: "sk-ant-explicit" }
    });
    expect(other.env.ANTHROPIC_API_KEY).toBe("sk-ant-explicit");

src/github-action/entrypoint.ts (source)

const keyProvider = applyLlmApiKey(env, inputs.models);
  if (keyProvider !== undefined) {
    const storage = opts.authStorage ?? createFileAuthStorage(getCodegeniePaths(undefined, env));
    if (storage.get(keyProvider) !== undefined) {
      throw new CodegenieError(
        "invalid_args",
        `a stored codegenie login for ${keyProvider} on this runner would override llm-api-key; ...`
      );
    }
  }

The guard is deliberately scoped to the single provider llm-api-key was routed to; only that scoping decides whether an unrelated stored login blocks a valid run.

tests/github-action.test.ts (source)

      authStorage: { get: () => undefined },   // runWithModels, line 1308
...
        authStorage: { get: (provider) => (provider === "openrouter" ? stored : undefined) },  // line 1411

The only two authStorage injections in this suite: the failing case injects an openrouter login, while the "unaffected" case goes through runWithModels, whose stub reports no stored login for any provider.

Original assessments and supporting evidence (may overlap or disagree)

Original source material is retained for audit. The current conclusion is above; superseded assessments are labeled where supplied. Attribution does not prove semantic equivalence.

Original candidate metadata:

  • f1792113-f1: severity low, confidence medium

Original impact: f1792113-f1/failureMode

The second half of the test claims to prove that a stored login for a *different* provider does not block llm-api-key, but it runs through runWithModels, which injects `authStorage: { get: () => undefined }`. No stored login exists in that run, so the provider comparison in `storage.get(keyProvider)` is never discriminated. If the guard regressed to be provider-agnostic (e.g. checking a fixed provider or any stored credential), this test would still pass, and the only other authStorage test (line 1404-1418) asserts the throwing case, which such a regression also satisfies.

Original impact: f1792113-f1/whyThisMatters

A provider-agnostic regression would make the action hard-fail (throw invalid_args before the status comment is claimed) on self-hosted runners that hold any unrelated stored codegenie login, blocking all reviews for a valid llm-api-key configuration, with no test signalling the break.

Original verification: f1792113-f1/verification

Re-run the suite with the guard mutated to `storage.get("openrouter")` or to `[...].some(...)` over all providers: tests at lines 1404-1425 still pass because the negative case's stub returns undefined for every provider.

Original fix: f1792113-f1/suggestedFix

Drive the "unaffected" case through executeGitHubActionCommand with the same provider-scoped stub, e.g. pass `authStorage: { get: (provider) => (provider === "openrouter" ? stored : undefined) }` while selecting `--model anthropic/claude-opus-5` and LLM_API_KEY set, and assert it resolves (ANTHROPIC_API_KEY applied, review argv produced).

Suggestion assessment: supported

The fix keeps the original requirement intact rather than weakening it: it injects a stored openrouter login while routing llm-api-key to anthropic, so storage.get(keyProvider) must return undefined and the run must proceed. It does not relax the throwing case at 1404-1418 (that assertion stays), and it cannot be satisfied by a provider-agnostic guard. runWithModels does not accept an authStorage override (its extra parameter only carries env/comments), so routing the case through executeGitHubActionCommand directly, as proposed, is the only way to supply the provider-scoped stub.

Behavioral requirement (established): llm-api-key must be refused only when a stored codegenie login exists for the provider llm-api-key was routed to; a stored login for any other provider must leave the run working (env key applied, review argv produced).

src/github-action/entrypoint.ts

const keyProvider = applyLlmApiKey(env, inputs.models);
  if (keyProvider !== undefined) {
    const storage = opts.authStorage ?? createFileAuthStorage(getCodegeniePaths(undefined, env));
    if (storage.get(keyProvider) !== undefined) { throw new CodegenieError("invalid_args", ...) }

Establishes the provider-scoped requirement the fix must exercise.

tests/github-action.test.ts

1295-1319 runWithModels(..., extra: { env?; comments? }) { ... authStorage: { get: () => undefined }, ... }

Shows the helper hard-codes an empty storage and offers no override, so the fix must call executeGitHubActionCommand directly.

Original test: f1792113-f1/suggestedTest

it("allows llm-api-key when the stored login belongs to another provider") — inject the openrouter `stored` entry, run with `--model anthropic/claude-opus-5` and LLM_API_KEY=sk-ant-explicit, expect no throw, expect env.ANTHROPIC_API_KEY === "sk-ant-explicit", and expect runReview to have been called.

Suggestion assessment: supported

The proposed assertions discriminate the three cases correctly. Against the observed gap: with the openrouter stored entry present and --model anthropic/claude-opus-5 + LLM_API_KEY, the provider comparison is finally live. Against a symptom-hiding remedy (deleting or softening the misleading comment, or widening the stub to return undefined again), the test still requires a real stored entry for a foreign provider, so it would not pass vacuously. Against a provider-agnostic regression (storage.get("openrouter") or any-credential check) the call throws invalid_args and the expectations on no-throw, ANTHROPIC_API_KEY and runReview having been called all fail. The correct provider-scoped implementation passes: keyProvider is anthropic, the stub returns undefined for anthropic, and the existing line 1424 assertion already demonstrates ANTHROPIC_API_KEY is set to the llm-api-key value on this path. It does not over-constrain (no exact argv/ordering demands beyond runReview being invoked).

... (truncated)

pkieltyka and others added 2 commits September 25, 2026 12:26
- llm-api-key's single-key rule now requires one API-key env var rather
  than one provider id, so provider pairs that share a var (moonshotai /
  moonshotai-cn, opencode / opencode-go, cloudflare-*) work with one key;
  competing vars are cleared and the stored-login guard runs per provider.
- Validate model/models after the trigger gate, so a broken block fails
  real triggers but unrelated comments skip instead of going red.
- Restore discriminated decision-record variants.
- Reuse providerKnown for alias provider validation.
- Normalize the requested alias only in the event gate, stripping
  surrounding quotes/backticks/brackets and trailing punctuation; alias
  names must start and end with a letter or digit so all stay reachable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxBabX2aBd6eRLJryVci78
Bump the package to 0.7.0 and pin the documented action references to
v0.7.0, the first release with the `models` input.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NxBabX2aBd6eRLJryVci78
@pkieltyka
pkieltyka merged commit 1f79ecd into master Sep 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant