Skip to content

[patch] [bugfix]: Restore AI issue auto-reply by moving from GitHub Models to Copilot CLI - #3098

Merged
Fidelia Nawar (fidelianawar) merged 21 commits into
devfrom
fidelianawar-fix-github-issues-actions-bot
Sep 4, 2026
Merged

[patch] [bugfix]: Restore AI issue auto-reply by moving from GitHub Models to Copilot CLI#3098
Fidelia Nawar (fidelianawar) merged 21 commits into
devfrom
fidelianawar-fix-github-issues-actions-bot

Conversation

@fidelianawar

@fidelianawar Fidelia Nawar (fidelianawar) commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Problem

The AI issue auto-reply workflow has been silently dead since 2026-07-30, when GitHub Models was retired.

Every model in MODELS_MODEL now returns HTTP 410 github_models_retirement_brownout. I confirmed this is still true today:

POST https://models.github.ai/inference/chat/completions
→ 410 {"code":"github_models_retirement_brownout"}

The failure is invisible: the generate step warns, emits empty text, and exits 0, so Post reply skips on its steps.ai.outputs.text != '' guard and the run goes green while nobody gets an answer.

Concrete example — #3082 was filed on 2026-08-20 and has never received a reply. The workflow did run (32371193675, 32371193495); the gate passed and the model call was attempted:

← Models API responded HTTP 410 (model=openai/gpt-5, attempt 1/3)
← Models API responded HTTP 410 (model=openai/gpt-4.1, attempt 1/3)
← Models API responded HTTP 410 (model=openai/gpt-4o, attempt 1/3)
← Models API responded HTTP 410 (model=openai/gpt-4o-mini, attempt 1/3)
##[warning]No model in the preference list returned 2xx.

Fix

Move to Copilot CLI, the supported way to run AI in Actions. It authenticates with the built-in GITHUB_TOKEN — no PAT, no API key. That mattered here: this repo has zero Actions secrets, so any provider requiring a key (Azure AI Foundry, direct OpenAI) would have needed an admin to provision one first.

  • permissions: swap the retired models: read for copilot-requests: write.
  • Install @github/copilot; invoke with --no-ask-user and --disable-builtin-mcps to keep the run non-interactive and hermetic. No --yolo: it is --allow-all, and nothing here needs it.
  • Lock the agent out of all tools. The prompt embeds attacker-controlled issue text, so the run is text-in/text-out as the Models API was. --available-tools "" is treated as unset and enables everything, and the deny rule is shell, not bash — both verified on a runner — so lockdown is expressed as a one-entry allowlist of an inert tool. A guard then discards the reply if any tool outside that allowlist is requested.
  • Randomise the GITHUB_OUTPUT heredoc delimiter. The reply is model-generated, so a literal EOF line in a comment would have closed the heredoc early and truncated the posted comment.
  • Bound the model call with timeout -k 30s 10m, restoring the ceiling curl --max-time 120 used to provide. Its exit code lands in the existing warn-and-skip branch (verified on a runner: hang 124, TERM-ignoring child 137).

The existing failure contract is preserved exactly — warn, emit empty text, exit 0, let Post reply skip. A flaky model call still must not fail the run or page anyone.

Also: reference budget

The 8 KB reference cap existed only because GitHub Models capped input at 8000 tokens/request. It was truncating the curated grounding set from 46 KB down to 8 KB — on the #3082 run: Reference material truncated: was 46358B, now 8000B.

Copilot CLI has no comparable per-request cap, so the manifest is now sent whole. The caps remain as a runaway guard for forks that override them downward.

Validation

  • yaml.safe_load parses; step graph is gate → Install Copilot CLI → ai → Post reply.
  • bash -n clean on the extracted generate step.
  • Ran the prompt-assembly path locally against the new budgets:
before after
reference material 8,000 B (truncated) 84,932 B (untruncated)
final prompt 91,190 B
  • Confirmed no stale references to MODELS_MODEL / models.github.ai / GH_MODELS_MODEL remain.

Validated against a live issue

Ran the real Install + Generate steps from this branch against issue #3071 on a runner. First run went green but produced nothing: the lockdown guard counted every tool request, including the inert allowlisted entry the model actually calls (3 × list_agents), so it discarded the reply — which would have happened on every issue. Fixed to count only requests outside the allowlist; same run then produced a 2.3 KB reply, posted to #3071.

This exercises grounding, prompt assembly, the CLI invocation and JSON extraction. It does not exercise the gate or the issues trigger: those always run the default-branch copy of a workflow, so they can only be verified after merge.

…odels to Copilot CLI

GitHub Models (models.github.ai) was retired on 2026-07-30. Every model in
MODELS_MODEL now returns HTTP 410 github_models_retirement_brownout, so the
"Generate AI reply" step emitted empty text and "Post reply" skipped on its
non-empty guard. The workflow reported success while replying to nobody --
issue #3082 is one of the issues that silently went unanswered.

Replace the Models HTTP call with Copilot CLI, which is the supported way to
run AI in Actions and authenticates with the built-in GITHUB_TOKEN. This repo
has no Actions secrets, so a provider needing an API key was not an option.

- permissions: swap the retired `models: read` for `copilot-requests: write`.
- Install @github/copilot and invoke it with --yolo (required for
  non-interactive runs), --no-ask-user and --disable-builtin-mcps to keep the
  run hermetic and autonomous.
- Hand the prompt over on disk instead of via -p. The assembled prompt is
  ~90 KB of Objective-C, Markdown and shell metacharacters; passing it as an
  argv string is a quoting minefield. Copilot reads the file and writes the
  finished comment to ai_reply.md, so neither prompt nor reply transits the
  shell.
- Randomise the GITHUB_OUTPUT heredoc delimiter. The reply is model-generated,
  so a literal "EOF" line would have closed the heredoc early and truncated
  the posted comment.
- Preserve the existing failure contract: warn, emit empty text, exit 0, and
  let "Post reply" skip. A flaky model call still must not fail the run.
- Add timeout-minutes so a runaway agent cannot hang the job.

Raise the reference-material budgets. The 8 KB cap existed only because
GitHub Models capped input at 8000 tokens per request; it truncated the
curated grounding set from 46 KB down to 8 KB. Copilot CLI has no comparable
cap, so the manifest is now sent whole -- verified locally at 84,932 B
assembled and untruncated, and it now includes MSALCIAMAuthority.h and
MSALSilentTokenParameters.h, which the old cap cut off.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread .github/ai-prompts/reference-files.txt

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The Copilot CLI step currently relies on the tool writing ai_reply.md as a side-effect, which can result in empty output and the workflow still skipping comment posting.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Restores the repository’s automated AI issue auto-reply workflow after GitHub Models retirement by switching the generation step to Copilot CLI, keeping the existing “warn + emit empty text + exit 0” failure contract so runs don’t fail noisily.

Changes:

  • Replaces models: read + GitHub Models API calls with Copilot CLI installation and invocation, using copilot-requests: write.
  • Raises the reference-material byte budgets (via env overrides) so the full curated grounding manifest can be included in prompts again.
  • Updates prompt-budget documentation/comments to reflect the Copilot CLI-based flow.
File summaries
File Description
.github/workflows/ai-issues-auto-reply.yml Switches AI generation from GitHub Models to Copilot CLI, updates permissions, adds install step, increases prompt/reference budgets.
.github/ai-prompts/reference-files.txt Updates manifest budget commentary to match Copilot CLI + raised caps behavior.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/ai-issues-auto-reply.yml Outdated
…efore merge)

issues/issue_comment events always run the workflow file from the default
branch, so the rewritten auto-reply cannot be exercised before it merges.
push events use the branch's own file, so this proves the new path works:
npm install, GITHUB_TOKEN auth, the --yolo invocation, the on-disk prompt
handoff, the reply-file guard and the randomised GITHUB_OUTPUT delimiter.

POST_REPLY defaults to false: the reply goes to the job summary and an
artifact for review before anything is posted to a real customer issue.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 3, 2026 17:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The PR introduces a “temporary / delete before merging” workflow file and also needs reliability hardening (retry) and version pinning decisions for Copilot CLI to avoid silent regressions.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:308

  • Issue: npm install -g @github/copilot installs the latest Copilot CLI on every run.

Impact: This makes the workflow non-deterministic and can break unexpectedly if a new Copilot CLI release changes flags/behavior. It also increases supply-chain risk versus pinning (the rest of this repo’s workflows typically pin Actions by SHA).

Recommendation: Pin the Copilot CLI package to a known-good version (or at least a major) and bump it intentionally when needed, e.g. npm install -g @github/copilot@<version>.

This issue also appears on line 686 of the same file.

.github/workflows/zz-smoke-copilot-reply.yml:39

  • Issue: npm install -g @github/copilot installs an unpinned Copilot CLI version.

Impact: The smoke test may start failing (or behave differently) when Copilot CLI changes, which reduces its usefulness as a validation harness.

Recommendation: Pin @github/copilot to a specific version (or major) so this smoke test remains stable while you validate the migration.

      - name: Install Copilot CLI
        run: npm install -g @github/copilot

.github/workflows/ai-issues-auto-reply.yml:690

  • Issue: The Copilot CLI invocation is single-shot. If Copilot CLI transiently fails (non-zero exit or tool hiccup), the step emits empty text and exits 0, so the run still goes green but no reply is posted.

Impact: This recreates the “silent no-reply” failure mode during transient outages (just with a different underlying cause), reducing the reliability of the auto-reply workflow.

Recommendation: Add a small bounded retry loop (e.g., 2–3 attempts with backoff), treating both non-zero exit and an empty reply file as retryable, before falling back to the existing warn-and-skip behavior.

          set +e
          copilot \
            --yolo \
            --no-color \
            --no-ask-user \
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/workflows/zz-smoke-copilot-reply.yml Outdated
Reply reviewed from the previous run's artifact. Flip to actually comment
on the target issue. This file is deleted before merge.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 3, 2026 17:31
Purpose served: the run proved npm install, GITHUB_TOKEN auth, the --yolo
invocation, the on-disk prompt handoff and the reply-file guard all work on
a real runner, and the generated reply was posted to the target issue.

Removing it before merge. It is push-triggered with POST_REPLY=true, so
leaving it in place would post a duplicate comment on every push.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The temporary smoke-test workflow is currently merge-dangerous (can spam a real issue) and the main workflow’s Copilot call lost retry/backoff behavior, reducing operational reliability.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:696

  • The previous GitHub Models path had bounded retries/backoff across transient failures. The Copilot CLI call is now a single attempt; any brief network/tooling hiccup will cause the workflow to skip replying for that issue/comment.

Impact: increased flakiness and lower reply rate, especially during transient GitHub outages.

Recommendation: add a small retry loop (e.g., 3 attempts with backoff) around the copilot invocation while preserving the existing warn-and-skip contract.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 3, 2026 17:35
…g manifest

The manifest was entirely Objective-C headers, so any issue about the Swift
native auth state machine reached the model with zero grounding -- the
system prompt forbids answering ungrounded, so those replies were destined
to be useless or fabricated. Native auth is a large share of inbound issues
(e.g. #3078, about SignInAfterResetPasswordState and onSignInAwaitingMFA).

Add the public surface only: entry point, sign-in/sign-up/MFA/reset states,
their delegates, and the error types customers actually see.

Verified strip_and_cap handles Swift: the header skip trips on the @objc
attribute, so the MIT block is dropped and output starts at the declaration.
Assembled reference is ~138 KB against the 200 KB cap.

Also re-adds the temporary smoke workflow, now targeting #3078 and using the
real strip_and_cap so Swift stripping is exercised faithfully. POST_REPLY is
false pending review. Deleted before merge.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The workflow enables tool-executing Copilot runs (--yolo) on untrusted issue content, creating a high-severity prompt-injection/token-exfiltration risk that should be mitigated before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

.github/workflows/ai-issues-auto-reply.yml:694

  • The workflow currently assumes Copilot CLI will write the final Markdown into ai_reply.md, but nothing in the shell command enforces that — the file is only created if the model decides to do so. This makes the success path fragile (empty replies even when Copilot produced valid stdout).

Impact: the run can go green while still posting nothing, reintroducing the same “silent failure” mode you’re trying to eliminate.

Recommendation: capture Copilot CLI stdout into REPLY_FILE directly (and adjust the prompt to tell Copilot to print the finished comment to stdout).

            --log-level none \
            --model "${COPILOT_MODEL:-auto}" \
            -p "Read the file ${PROMPT_FILE}. It contains a system prompt followed by the GitHub issue to answer. Follow those instructions and compose the reply comment they describe. Do not modify any file in this repository, do not run git, and do not post anything to GitHub. Your only side effect must be writing the finished comment — GitHub-flavoured Markdown, no preamble, no code fence around the whole thing — to ${REPLY_FILE}."
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/workflows/ai-issues-auto-reply.yml Outdated
Copilot AI review requested due to automatic review settings September 3, 2026 17:40
Reply reviewed from the previous run's artifact and fact-checked against the
native auth sources: onSignInAwaitingMFA, AwaitingMFAState.requestChallenge
and the inherited isGeneralError all exist as cited. Deleted before merge.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Both target issues have been replied to. Removing before merge: the workflow
is push-triggered with POST_REPLY=true, so leaving it would post a duplicate
comment on every push.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

A temporary smoke-test workflow is being added despite “DELETE BEFORE MERGING”, and a couple of reliability/robustness concerns should be addressed to preserve the workflow’s intended “stay green” failure contract.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:309

  • The Copilot CLI install step can fail the entire workflow run (npm registry/network/transient failures), even though the workflow's stated contract is to remain green and skip posting when AI generation is unavailable.

Issue: If npm install -g @github/copilot fails, the job stops before the tolerant "Generate AI reply" step runs.
Impact: Auto-reply becomes brittle (and visibly red) on transient npm failures, reintroducing a reliability regression.
Recommendation: Make the install step non-fatal so the next step can warn-and-skip cleanly, consistent with the previous failure contract.
.github/workflows/ai-issues-auto-reply.yml:721

  • The heredoc delimiter randomization relies on openssl, which is an extra external dependency in the critical path.

Issue: If the runner image ever changes such that openssl is missing or fails, the step will exit non-zero under set -e after the AI reply is generated.
Impact: This can break the intended failure contract (warn-and-skip / stay green) and prevent posting replies.
Recommendation: Generate the delimiter using bash-only primitives (e.g., $RANDOM) to avoid external tool dependencies while still making delimiter collisions extremely unlikely.

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/ai-prompts/reference-files.txt Outdated
Copilot AI review requested due to automatic review settings September 3, 2026 17:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The Copilot CLI --yolo usage materially increases prompt-injection blast radius with an issues: write token, and the new .swift manifest entries are not handled correctly by the current manifest inlining logic.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:308

  • Issue: This installs Copilot CLI without emitting the installed version. If the npm package publishes a breaking change (or a runner image ships a different Node/npm), troubleshooting becomes much harder because logs don’t show what CLI build ran.

Impact: A future CLI regression can look like an intermittent model failure and silently disable replies while leaving the workflow green.

Recommendation: Print copilot --version immediately after install so runs capture the exact CLI version in logs.

.github/workflows/ai-issues-auto-reply.yml:691

  • Severity: High – Issue: copilot --yolo enables automatic approval of tool execution (file/shell). Because the prompt is derived from untrusted issue/issue_comment content, this makes the job vulnerable to prompt-injection that can run arbitrary commands and potentially exfiltrate the job’s GITHUB_TOKEN (which currently has issues: write).

Impact: A malicious issue author could use the AI agent to leak the token or perform unintended GitHub API operations during the run.

Recommendation: Split the workflow into two jobs: (1) AI generation job with minimal permissions (contents: read, copilot-requests: write only) and no issues: write, then (2) a posting job with issues: write that consumes the generated markdown (job output/artifact). This preserves functionality while sharply reducing blast radius if the agent is coerced into running tools.

          copilot \
            --yolo \
            --no-color \
            --no-ask-user \
            --disable-builtin-mcps \

.github/ai-prompts/reference-files.txt:75

  • Issue: This manifest now includes several .swift files, but ai-issues-auto-reply.yml currently treats all non-.md entries as Objective-C and runs them through strip_and_cap (which skips content until it hits #import, NS_ASSUME_NONNULL_BEGIN, or a line starting with @). For Swift files, that can drop the leading docs/imports (or even most of the file) and wraps the output in an objc code fence.

Impact: The added Native Auth grounding may be missing or malformed in the prompt, reducing answer quality and making citations inaccurate.

Recommendation: Update the workflow’s manifest loop to handle *.swift explicitly (e.g., wrap in a swift fence and avoid Obj-C-specific stripping, or implement Swift-aware stripping).

# ---- Native authentication (Swift) ----
# Native auth is a large share of inbound issues but had no grounding here,
# so replies about sign-in/sign-up/MFA state machines had nothing to cite.
# Public API only: entry point, state machine states, delegates and the
# error types customers actually see.
MSAL/src/native_auth/public/MSALNativeAuthPublicClientApplication.swift
MSAL/src/native_auth/public/state_machine/state/SignInStates.swift
MSAL/src/native_auth/public/state_machine/state/SignInAfterResetPasswordState.swift
MSAL/src/native_auth/public/state_machine/state/SignInAfterSignUpState.swift
MSAL/src/native_auth/public/state_machine/state/MFAStates.swift
MSAL/src/native_auth/public/state_machine/state/ResetPasswordStates.swift
MSAL/src/native_auth/public/state_machine/state/SignUpStates.swift
MSAL/src/native_auth/public/state_machine/delegate/SignInDelegates.swift
MSAL/src/native_auth/public/state_machine/delegate/SignInAfterResetPasswordDelegate.swift
MSAL/src/native_auth/public/state_machine/delegate/SignInAfterSignUpDelegate.swift
MSAL/src/native_auth/public/state_machine/delegate/MFADelegates.swift
MSAL/src/native_auth/public/state_machine/error/MSALNativeAuthError.swift
MSAL/src/native_auth/public/state_machine/error/SignInAfterResetPasswordError.swift
MSAL/src/native_auth/public/state_machine/error/SignInAfterSignUpError.swift
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Final config verified: positive control executed the shell (toolRequests=1),
hardened invocation did not (toolRequests=0, NO_TOOLS).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The workflow currently installs an unpinned Copilot CLI version and contains mismatches between stated behavior (in PR description/comments) and the actual Copilot invocation, which risks future silent breakage and maintainability/security misunderstandings.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:352

  • Issue: The workflow installs Copilot CLI with npm install -g @github/copilot without pinning a version.
    Impact: A new upstream release can break this workflow (or change the JSONL schema/flags) without any repo change, making the auto-reply silently stop again.
    Recommendation: Pin @github/copilot to a known-good version (or make the version an explicit env var) and update it intentionally as part of normal maintenance.
    .github/workflows/ai-issues-auto-reply.yml:736
  • Issue: The PR description says the prompt is passed “on disk, not through -p” and that --yolo is required for non-interactive runs, but this workflow passes the prompt via -p "$(cat ...)" and explicitly omits --yolo.
    Impact: Reviewers and future maintainers may rely on the PR description’s security/robustness rationale and draw the wrong conclusions about quoting risk and non-interactive behavior.
    Recommendation: Align the implementation and description (either switch to a file-based prompt option + --yolo if that’s still required, or update the PR description/inline comments to reflect the current approach).

.github/workflows/ai-issues-auto-reply.yml:704

  • Issue: The security comment claims the allowlist leaves “no … fetch”, but the allowlisted tool is named fetch_copilot_cli_documentation, and the workflow also discards replies if any tool request is observed.
    Impact: The comment is misleading about what’s permitted and why; it makes the security model harder to reason about during future changes.
    Recommendation: Reword this block to (1) accurately describe the single allowlisted tool, and (2) explicitly tie it to the tool-request discard guard below.
          #   2. --available-tools allowlists only `list_agents`, which lists
          #      background agents and touches no file, shell or network. There
          #      is no "empty" allowlist: `--available-tools ""` is treated as
          #      unset and restricts nothing, so one inert entry is the way to
          #      express "no useful tools". Allowlist rather than --deny-tool,
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/workflows/ai-issues-auto-reply.yml Outdated
Copilot AI review requested due to automatic review settings September 3, 2026 18:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The workflow introduces a new AI execution path and multi-job permission/artifact choreography that should be validated by a human with end-to-end Actions runtime context.

Review details

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:33

  • Issue: The workflow-level concurrency.group uses ${{ github.event.issue.number }}, but workflow_dispatch runs don’t have github.event.issue, so the group resolves to ai-reply- for backfill runs.

Impact: All manually-triggered backfill runs will share the same concurrency group (and this could become confusing if additional non-issue triggers are added later).

Recommendation: Fall back to a unique value (e.g. github.run_id) when issue.number is unavailable, similar to the pattern used in other workflows in this repo.

.github/workflows/ai-issues-auto-reply.yml:833

  • Issue: The comment above the github-script step says the AI body is passed via env, but the implementation now reads it from ai_reply.md.

Impact: Stale guidance can mislead future maintainers into “simplifying” this back to step outputs/env interpolation and reintroducing the escaping problem this change is avoiding.

Recommendation: Update the comment to match the new artifact-file approach (and keep the rationale about avoiding ${{ }} interpolation with model output).

          # Pass the AI body via env (not inline ${{ }} interpolation) so
          # backticks, ${...}, and other JS-significant characters in the AI
          # output can't break the script source. The earlier inline form
          # crashed with SyntaxError: Unexpected identifier 'MSAL...' when
          # the AI reply contained ``MSALInteractiveTokenParameters`` markdown
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Comments drop from 73 to 34 added lines. Kept only what stops someone
reintroducing a hole or breaking generation:
- --available-tools "" is treated as unset and enables every tool
- --deny-tool bash still executes commands; the rule name is shell
- an unrecognised allowlist entry fails closed
- -p is the only non-interactive prompt input; stdin returns empty

Everything else -- the GitHub Models retirement history, jq mechanics, ARG_MAX
arithmetic -- is in the PR description rather than the file. The PR is now net
negative on lines.

No functional change.
Copilot AI review requested due to automatic review settings September 3, 2026 18:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The workflow changes include reliability/documentation issues (e.g., unguarded Copilot CLI install and stale comments) that can break the intended “warn-and-skip” contract or mislead future maintenance.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:339

  • Issue: Download gate payload failing will currently fail the generate job (no continue-on-error).

Impact: A transient artifact download failure would make the workflow red, and in ping_copilot mode it also undermines the intended behavior of skipping replies safely.

Recommendation: Make this download step continue-on-error: true (matching the post job’s download) so the job can fall back to a warn-and-skip path.
.github/workflows/ai-issues-auto-reply.yml:342

  • Issue: The Install Copilot CLI step will fail the entire generate job if npm install -g @github/copilot hits a transient registry/network issue.

Impact: This breaks the workflow’s stated “warn-and-skip, exit 0” failure contract and can cause unexpected red CI runs even when the intended behavior is to skip posting.

Recommendation: Mark the install step as continue-on-error: true so failures flow into the existing copilot exit-code handling (which already warns and exits 0).
.github/workflows/ai-issues-auto-reply.yml:794

  • Issue: The comment above the github-script step says the AI body is passed via env, but the implementation now reads the body from ai_reply.md.

Impact: This is misleading for future maintainers and increases the chance of reintroducing the earlier interpolation/backtick breakage while “cleaning up” comments.

Recommendation: Update the comment to describe the artifact-file approach.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

…nd job split

Rebuilt from dev and applied only what the migration requires, rather than
un-picking the restructure. Diff is now 79 insertions / 153 deletions.

Removed, as new machinery this repo never had:
- the gate/generate/post job split
- artifact upload/download for prompt_input.json and ai_reply.md

The split was justified when Copilot ran with --yolo and a live shell: the
concern was an injected prompt exfiltrating a token that could write issues.
That premise no longer holds. Every tool is now disabled and verified so
(positive control executed a shell, hardened run did not: toolRequests 1 vs
0), which makes the invocation text-in/text-out -- the same posture as the
GitHub Models REST API this replaces. The split was restoring parity that the
tool lockdown already restores, at the cost of ~90 lines and an artifact
handoff that had never been exercised end to end.

The reply travels via GITHUB_OUTPUT exactly as before, and the Post reply step
is byte-identical to dev.

One deliberate difference from dev: a random heredoc delimiter. The body is
model-generated, so a literal EOF line would close the heredoc early and
truncate the posted comment. Verified with a fixture containing an EOF line,
backticks and ${...}.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 3, 2026 18:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The Copilot CLI step is missing --yolo (needed for non-interactive Actions runs) and currently discards stderr, which together can reintroduce silent/non-actionable failures.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

.github/workflows/ai-issues-auto-reply.yml:669

  • Issue: The Copilot CLI stderr is fully discarded (2>/dev/null).

Impact: If Copilot starts failing (auth/permissions/model selection/CLI regression), the job will only surface the exit code with no actionable diagnostics, making it harder to restore the workflow when it breaks again.

Recommendation: Don’t drop stderr; let it appear in the Actions log (token-like values should still be redacted by Actions).

            -p "$(cat "$PROMPT_FILE")" > "$RAW_FILE" 2>/dev/null
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/workflows/ai-issues-auto-reply.yml Outdated
This PR's job is to restore the bot after the GitHub Models retirement.
Three changes went beyond that and are removed:

- MAX_REFERENCE_BYTES_OVERRIDE / MAX_PER_FILE_BYTES_OVERRIDE /
  MAX_DYNAMIC_BYTES_OVERRIDE raised grounding material from 8KB to
  200KB. That changes what the model sees, so it changes reply
  content -- a behavior change, not a fix. The ${VAR_OVERRIDE:-default}
  indirection already existed in dev as an unused extension point and
  is left untouched, so this can be revisited on its own merits.

- timeout-minutes: 15 on the generate step was new, and would fail the
  job rather than warn-and-skip, which contradicts the surrounding
  error handling.

- reference-files.txt was only touched to document the raised caps, so
  it reverts to dev exactly and leaves the PR at one file.

Diff: 79/153 across two files -> 67/147 in one.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2aa548b6-643e-4b76-a818-98860a8b8052
Copilot AI review requested due to automatic review settings September 3, 2026 19:40
dev bounded its model call with `curl --max-time 120`. The Copilot CLI
invocation that replaced it had no bound, so a hung call would have run
until the job-level limit. `timeout -k 30s 10m` restores that bound;
exit 124 flows into the existing warn-and-skip path, keeping the run
green rather than failing the job.

Exit codes verified on ubuntu-latest: hang=124, success=0, failure=1
(passthrough), TERM-ignoring child=137.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The workflow currently omits a pinned Node.js setup (Copilot CLI requires a sufficiently new Node) and lacks an explicit generation timeout, risking silent non-functionality or hung jobs.

Review details

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:303

  • Issue: npm install -g @github/copilot depends on a sufficiently new Node.js runtime, but this workflow never sets the Node version explicitly.

Impact: On runners where the default Node version is below Copilot CLI’s required minimum, the install and/or copilot execution can fail, causing the workflow to warn and emit empty output (so auto-replies remain silently non-functional).

Recommendation: Add an actions/setup-node step (gated the same way) to pin Node to a supported version (e.g. 22+) before installing Copilot CLI.

.github/workflows/ai-issues-auto-reply.yml:314

  • Issue: The Copilot generation step has no explicit timeout-minutes.

Impact: If npm/Copilot CLI hangs (network stalls, auth prompt regression, etc.), the job can block until GitHub’s default job timeout, tying up the concurrency group and delaying replies to other issues.

Recommendation: Add a step-level timeout (e.g. 15 minutes) to keep the workflow self-limiting as described in the PR rationale.

      - name: Generate AI reply (Copilot CLI)
        id: ai
        if: steps.gate.outputs.should == 'true'
        env:
          GITHUB_TOKEN: ${{ github.token }}
          COPILOT_MODEL: ${{ env.COPILOT_MODEL }}
          MODE: ${{ steps.gate.outputs.mode }}
          ISSUE_TITLE_JSON: ${{ toJSON(github.event.issue.title) }}
          ISSUE_BODY_JSON: ${{ toJSON(github.event.issue.body || '') }}
        run: |
  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 3, 2026 19:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The workflow still defaults to truncating reference grounding to 8KB and has mismatches with the PR’s stated behavior (including missing timeout-minutes), risking continued silent degradation/noncompliance with the intended fix.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:40

  • Issue: The workflow still defaults to truncating Tier-2 reference material to 8,000 bytes (MAX_REFERENCE_BYTES="${MAX_REFERENCE_BYTES_OVERRIDE:-8000}" and head -c "$MAX_REFERENCE_BYTES" ...).

Impact: This contradicts the PR description’s goal of sending the reference manifest untruncated under Copilot CLI, and will continue to cut grounding content unless a repo/org variable sets MAX_REFERENCE_BYTES_OVERRIDE.

Recommendation: Set a higher default budget in the workflow env (while keeping the override mechanism so forks can dial it down).
.github/workflows/ai-issues-auto-reply.yml:686

  • Issue: The tool-lockdown verification only counts .data.toolRequests on events with type == "assistant.message". Copilot CLI’s JSON stream can emit tool request events as separate records/types, so this check can miss tool usage and still publish the assistant message.

Impact: If a tool request slips through --available-tools (or the schema changes), the workflow could post output influenced by tool execution while the guard incorrectly reports zero tool requests.

Recommendation: Detect tool usage across all emitted JSON events (e.g., any non-empty .data.toolRequests anywhere, or any event type containing tool).

.github/workflows/ai-issues-auto-reply.yml:650

  • Issue: The PR description says the prompt is passed “on disk, not through -p” and that --yolo is required, but the implementation uses -p "$(cat "$PROMPT_FILE")" and does not use --yolo.

Impact: Future maintainers relying on the PR description may "fix" the workflow back into a broken/non-working state (e.g., by trying stdin again or reintroducing --yolo).

Recommendation: Update the PR description (or add a short comment here) to match the final invocation constraints: -p is required for non-interactive runs, stdin yields empty, and tools are intentionally disabled (no --yolo).

          # -p is the only non-interactive prompt input (stdin returns empty).
          # "$(cat …)" is one argv element; bash does not re-scan it.
          PROMPT_FILE="$(mktemp)"
          RAW_FILE="$(mktemp)"
          printf '%s\n\n%s\n' "$SYSTEM_PROMPT" "$USER_PROMPT" > "$PROMPT_FILE"
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread .github/workflows/ai-issues-auto-reply.yml
The guard counted every tool request, including the inert allowlisted
entry the model actually calls. A CI run against issue #3071 showed
three list_agents requests tripping it, so the job went green and
posted nothing -- which would have happened on every issue.

Count only requests outside the allowlist, so the guard still fires if
a tool escapes --available-tools. Verified end to end: same run now
yields a 2.3 KB reply.
Copilot AI review requested due to automatic review settings September 3, 2026 23:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The workflow still lacks a job-level timeout and does not ensure a compatible Node.js version for installing/running @github/copilot, which can cause silent skipping or hangs in production runs.

Review details

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/ai-issues-auto-reply.yml:304

  • Issue: @github/copilot is installed via npm, but the workflow doesn’t pin/ensure a compatible Node.js version. GitHub’s Copilot CLI npm package documentation indicates a Node.js version requirement (e.g., Node 22+).

Impact: If the runner’s preinstalled Node version is older (or changes in the future), npm install -g @github/copilot or the copilot invocation can fail, silently skipping replies.

Recommendation: Add an actions/setup-node step (pin a minimum Node version known to satisfy Copilot CLI) before installing the CLI.

.github/workflows/ai-issues-auto-reply.yml:48

  • Issue: The job currently has no job-level timeout-minutes, even though the PR description calls out adding a 15-minute timeout. The script bounds the copilot call, but other steps (e.g., npm install -g @github/copilot) can still hang indefinitely.

Impact: A stalled install/network operation can tie up concurrency (ai-reply-<issue_number>) and block future auto-replies until the runner times out at the platform default.

Recommendation: Add timeout-minutes: 15 at the job level to guarantee the workflow can’t hang forever.

  ai_autoreply:
    if: github.event_name != 'workflow_dispatch'
    runs-on: ubuntu-latest
    concurrency:
      group: ai-reply-${{ github.event.issue.number }}
      cancel-in-progress: false
  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The reference limits remain unchanged, and the Copilot CLI dependency is not version-pinned.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 2
  • Review effort level: Balanced

- name: Generate AI reply (GitHub Models)
- name: Install Copilot CLI
if: steps.gate.outputs.should == 'true'
run: npm install -g @github/copilot
# "$(cat …)" is one argv element; bash does not re-scan it.
PROMPT_FILE="$(mktemp)"
RAW_FILE="$(mktemp)"
printf '%s\n\n%s\n' "$SYSTEM_PROMPT" "$USER_PROMPT" > "$PROMPT_FILE"
@fidelianawar
Fidelia Nawar (fidelianawar) merged commit 8301205 into dev Sep 4, 2026
17 checks 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.

3 participants