[Daily #1330] mcp-server-tab — the MCP-server dropdown is intermittently not clickable within 3 s (recurrent 2×) #363
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Human-gated GitHub automation for the daily triage. | |
| # Phase 1 (propose): after the daily-stable run finishes red, run the triage | |
| # skill non-interactively and post the plan as a comment on the umbrella issue. | |
| # Creates nothing on its own. (workflow_run is used, NOT issues.opened: the | |
| # umbrella issue is created by daily-stable's GITHUB_TOKEN, and GitHub suppresses | |
| # workflow runs for GITHUB_TOKEN-raised events — an issues trigger would never | |
| # fire. workflow_run is exempt from that suppression.) | |
| # Phase 2 (execute): when a triage-team member replies "pode abrir" on that | |
| # umbrella, run the skill again to create/enrich the dedicated issues. | |
| # No code is mutated from CI: contents is read-only, so @stable removal stays a | |
| # manual/local PR (the skill's 2nd gate); allowedTools is Read,Bash. | |
| # NOTE: workflow_run / issue_comment triggers only fire from the workflow file | |
| # on the DEFAULT branch — the auto-triggers are live only after this merges to | |
| # main. Pre-merge, use the workflow_dispatch entry to test `propose` on a branch. | |
| name: Triage Dispatch | |
| on: | |
| workflow_run: | |
| workflows: ["Daily Stable E2E"] | |
| types: [completed] | |
| issue_comment: | |
| types: [created] | |
| workflow_dispatch: | |
| inputs: | |
| issue: | |
| description: "Umbrella issue number to (re)propose against" | |
| required: true | |
| # id-token: write is REQUIRED by anthropics/claude-code-action@v1 — it mints an | |
| # OIDC token to authenticate; without it the action fails fast with | |
| # "Could not fetch an OIDC token". It grants no repo write: contents stays read, | |
| # so @stable removal remains a manual/local PR. | |
| permissions: | |
| issues: write | |
| contents: read | |
| id-token: write | |
| # actions: read lets the propose job download the triggering daily run's | |
| # results.json artifact (playwright-json-daily-<run_id>) so Phase 5 can read | |
| # per-skip reasons instead of only the history file's skip total (#791). | |
| actions: read | |
| jobs: | |
| propose: | |
| name: Propose triage plan | |
| # workflow_dispatch is gated on a trusted actor: without this, any collaborator | |
| # who can dispatch a workflow could run the triage skill against an arbitrary | |
| # issue number. The workflow_run path needs no actor guard — it only fires from | |
| # the real Daily Stable E2E run and is already narrowed to schedule + failure. | |
| if: >- | |
| (github.event_name == 'workflow_dispatch' && | |
| contains(fromJSON('["rafaelgiln","Victor-w-Madeira","daniellicnerski1"]'), github.actor)) || | |
| (github.event_name == 'workflow_run' && | |
| github.event.workflow_run.conclusion == 'failure' && | |
| github.event.workflow_run.event == 'schedule') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| # Best-effort: pull the triggering daily's results.json so the skill's | |
| # INTAKE can pass --results and Phase 5 (SKIPS) reads real per-skip | |
| # reasons. Only the workflow_run path has a source run; a manual | |
| # workflow_dispatch has none, so it runs history-only (as before). Never | |
| # fails the job — if the artifact is missing/expired, propose degrades to | |
| # history-only and says so in the proposal. | |
| - name: Download triggering daily results.json (best-effort) | |
| if: github.event_name == 'workflow_run' | |
| continue-on-error: true | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| DAILY_RUN_ID: ${{ github.event.workflow_run.id }} | |
| run: | | |
| gh run download "$DAILY_RUN_ID" --repo "$GITHUB_REPOSITORY" \ | |
| -n "playwright-json-daily-$DAILY_RUN_ID" -D . \ | |
| || echo "::warning::results.json artifact unavailable for run $DAILY_RUN_ID — propose runs history-only." | |
| if [ -f results.json ]; then echo "results.json present ($(wc -c < results.json) bytes)."; else echo "no results.json — history-only."; fi | |
| # Do not start the agent when the triggering run produced nothing to triage | |
| # (#1178). Until this gate existed, the step above degraded to | |
| # "history-only" and the agent ran anyway: on 2026-07-31 the daily's four | |
| # shards all failed without a blob, the merge job died on `No report files | |
| # found in .../all-blobs`, no results.json was uploaded, and the agent spent | |
| # 28 of its 30 turns and $1.66 (its own log reports `num_turns` and | |
| # `total_cost_usd`) reconstructing a run that had recorded ZERO test results. | |
| # | |
| # The decision reuses `analyze()` from scripts/check-run-integrity.mjs — the | |
| # daily's own runguard logic (#1012) — so the two can never disagree, and so | |
| # the case that makes a naive test-count check wrong is handled: a PARTIAL | |
| # run, where some shards aborted in globalSetup while others executed | |
| # (#1058), still RUNS the agent. Skipping is loud (::warning:: + a run-summary | |
| # line), never silent; an unparseable-but-present report fails the step | |
| # rather than reading as "nothing to triage" (#1035). | |
| - name: Gate — does the triggering run give the agent anything to triage? | |
| id: triage_input | |
| run: node scripts/triage-input-gate.mjs --results results.json | |
| # The gate binds the AUTOMATIC path only. A `workflow_dispatch` is a human | |
| # asking for this triage with an explicit `--issue`, and it downloads no | |
| # artifact at all (there is no triggering run id), so gating it would refuse | |
| # the one path that exists for re-proposing on demand — including the | |
| # per-model A/B #1171 needs. Same reasoning as leaving `execute` ungated. | |
| - uses: anthropics/claude-code-action@v1 | |
| if: >- | |
| github.event_name == 'workflow_dispatch' || | |
| steps.triage_input.outputs.should_run_agent == 'true' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| prompt: "/langflow-e2e-triage --phase propose ${{ inputs.issue && format('--issue {0}', inputs.issue) || '' }}" | |
| # --model pinned (#1178): the action's default is `claude-opus-5[1m]`, and | |
| # nothing here needs Opus-tier reasoning at Opus-tier price. Sonnet 5 | |
| # keeps the 1M context window this job depends on (it reads CI logs) at | |
| # 3/5 of the per-token price — on the three measured runs, $4.71 → ~$2.80. | |
| # NOT haiku: its window is 200K, and the most expensive runs are the ones | |
| # with the largest input, so it would overflow exactly where it matters. | |
| # Worth an A/B once the input is bounded — via `workflow_dispatch --issue N` | |
| # on the same umbrella — and #1171 is the standing reminder that a cheaper | |
| # model has to be validated, not assumed. | |
| claude_args: '--allowedTools "Read,Bash" --max-turns 30 --model claude-sonnet-5' | |
| execute: | |
| name: Execute approved triage | |
| if: >- | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request == null && | |
| github.event.issue.state == 'open' && | |
| contains(github.event.issue.labels.*.name, 'daily-failure') && | |
| startsWith(github.event.comment.body, 'pode abrir') && | |
| contains(fromJSON('["rafaelgiln","Victor-w-Madeira","daniellicnerski1"]'), github.event.comment.user.login) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| concurrency: | |
| group: triage-execute-${{ github.event.issue.number }} | |
| cancel-in-progress: false | |
| steps: | |
| - uses: actions/checkout@v7 | |
| # Stamped BEFORE the agent runs so the guard below can tell the issues this | |
| # run created from every other open daily-failure issue. Minus a minute of | |
| # slack for clock skew between the runner and the API. | |
| - name: Mark the start of this run | |
| id: started | |
| run: echo "at=$(date -u -d '-1 minute' +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT" | |
| - uses: anthropics/claude-code-action@v1 | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| prompt: "/langflow-e2e-triage --phase execute --issue ${{ github.event.issue.number }}" | |
| # Same pin as propose (#1178). NOT gated on a report: execute is triggered | |
| # by a human "pode abrir" on a plan that already exists, so it has | |
| # something to do regardless of what the daily uploaded. | |
| claude_args: '--allowedTools "Read,Bash" --max-turns 40 --model claude-sonnet-5' | |
| # The contract gate for the AGENT path (#1035). | |
| # | |
| # An `issues.opened` trigger cannot do this job: the step above creates the | |
| # issues as GITHUB_TOKEN, and GitHub suppresses workflow runs for | |
| # GITHUB_TOKEN-raised events (the same constraint that put this whole | |
| # workflow on workflow_run). An issues-triggered gate would never fire here | |
| # while looking green — so the check runs inline instead, outside the agent | |
| # but inside its job. | |
| # | |
| # `if: always()` — a triage that died mid-way can still have created issues, | |
| # and those are exactly the ones worth checking. | |
| # `continue-on-error` — report, never block: a malformed issue still carries | |
| # evidence someone needs, so it gets a comment and a label, not a red job. | |
| - name: Guard — issues created by this run meet the dedicated-issue contract | |
| if: always() | |
| continue-on-error: true | |
| uses: ./.github/actions/guard-dedicated-issue | |
| with: | |
| since: ${{ steps.started.outputs.at }} | |
| github_token: ${{ github.token }} |