Files
wehub-resource-sync 7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

140 lines
5.4 KiB
YAML

name: Issue Research
# When a maintainer applies the `ldr_research` label to an issue,
# run LDR research on the issue title + body and post a comment
# with two sections: a brief, cautious response for the reporter,
# and adjacent context for maintainer triage.
#
# The same `ldr_research` label is reused from the PR workflow.
# GitHub gates by event type (`on: issues:` here vs
# `on: pull_request:` in e2e-research-test.yml), so they don't
# conflict.
on:
issues:
types: [labeled]
permissions: {} # Minimal top-level for OSSF Scorecard
jobs:
build-query:
name: Assemble query
if: github.event.label.name == 'ldr_research'
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
query: ${{ steps.assemble.outputs.query }}
env:
ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_BODY: ${{ github.event.issue.body }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- name: Sanitize and assemble query
id: assemble
run: |
# Strip control chars (defence-in-depth against weird issue
# bodies) and truncate to 4000 chars before embedding in the
# prompt. The issue body is semi-trusted user input — never
# eval'd, never shelled out, only passed to the LLM as text.
SAFE_TITLE=$(printf '%s' "$ISSUE_TITLE" | tr -d '\000-\010\013-\037\177' | head -c 500)
SAFE_BODY=$(printf '%s' "$ISSUE_BODY" | tr -d '\000-\010\013-\037\177' | head -c 4000)
{
cat <<'PROMPT_HEAD_EOF'
A user filed a GitHub issue against the Local Deep Research project. Produce a comment with two distinct sections:
(1) "**For the reporter**" — a brief, cautious, 2-4 sentence summary of likely diagnostic directions, framed as suggestions and not authoritative diagnosis. If you don't have enough context to be useful, say so plainly.
(2) "**For maintainers**" — adjacent external context: similar reports in other projects, relevant upstream library documentation, known issues with the components mentioned, and related discussions. Treat the maintainer as the primary audience for the substantive research.
Issue title:
PROMPT_HEAD_EOF
printf '%s\n' "$SAFE_TITLE"
cat <<'PROMPT_MID_EOF'
Issue body:
<<<ISSUE_BODY
PROMPT_MID_EOF
printf '%s\n' "$SAFE_BODY"
cat <<'PROMPT_TAIL_EOF'
ISSUE_BODY>>>
PROMPT_TAIL_EOF
} > query.txt
# Randomized delimiter so a query containing the literal delimiter
# on its own line cannot prematurely terminate the heredoc.
DELIM="LDR_QUERY_EOF_$$_${RANDOM}_$(date +%N)"
{
echo "query<<$DELIM"
cat query.txt
echo "$DELIM"
} >> "$GITHUB_OUTPUT"
research:
name: Run LDR research
needs: build-query
# Grant the perms the reusable's job needs:
# - contents: read for actions/checkout
# - actions: write for actions/upload-artifact@v5+
# Without this, the reusable's `permissions: contents: read` exceeds
# the inherited empty permissions and GitHub rejects the workflow at
# load time (startup_failure with zero jobs).
permissions:
contents: read
actions: write
uses: ./.github/workflows/ldr-research-reusable.yml
with:
query: ${{ needs.build-query.outputs.query }}
model: ${{ vars.LDR_RESEARCH_MODEL || 'google/gemini-2.0-flash-001' }}
provider: ${{ vars.LDR_PROVIDER || 'openrouter' }}
search-tool: ${{ vars.LDR_SEARCH_TOOL || 'serper' }}
strategy: ${{ vars.LDR_STRATEGY || 'langgraph-agent' }}
comment-header: '## 🤖 LDR Research'
comment-subheader: '_Auto-generated context for maintainer triage and the reporter — see disclaimer below._'
secrets:
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
SERPER_API_KEY: ${{ secrets.SERPER_API_KEY }}
post-comment:
name: Post issue comment
needs: research
# always() so the label-removal step runs even if research was skipped
# (e.g. build-query failed). The download/post steps are guarded by
# needs.research.outputs.success == 'true' so they self-skip in that
# case.
if: always()
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
env:
ISSUE_NUMBER: ${{ github.event.issue.number }}
LABEL_NAME: ${{ github.event.label.name }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- name: Download research artifact
if: needs.research.outputs.success == 'true'
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ needs.research.outputs.comment-artifact-name }}
- name: Post comment
if: needs.research.outputs.success == 'true'
run: |
gh issue comment "$ISSUE_NUMBER" --repo "${{ github.repository }}" -F comment.md
- name: Remove label for re-triggering
if: always()
run: |
gh issue edit "$ISSUE_NUMBER" --remove-label "$LABEL_NAME" 2>/dev/null || true