DEFI@home quorum #220
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
| name: DEFI@home quorum | |
| on: | |
| schedule: | |
| - cron: "0 6 * * *" | |
| push: | |
| branches: [main] | |
| paths: | |
| - "data/submissions/**" | |
| workflow_dispatch: | |
| concurrency: | |
| group: quorum | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| quorum: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - name: Run quorum | |
| id: quorum | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| run: | | |
| pnpm --silent --filter @defipunkd/validator run quorum -- --json > quorum-report.json | |
| cat quorum-report.json | |
| - name: Open / update aggregation issues | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const report = JSON.parse(fs.readFileSync('quorum-report.json', 'utf8')); | |
| // Group changes by protocol (slug); one aggregation issue per protocol. | |
| const bySlug = new Map(); | |
| for (const c of report.changes) { | |
| if (c.kind === 'insufficient' || c.kind === 'unchanged') continue; | |
| if (!bySlug.has(c.slug)) bySlug.set(c.slug, []); | |
| bySlug.get(c.slug).push(c); | |
| } | |
| const sectionFor = (c) => { | |
| if (c.kind === 'disagreement') { | |
| const dis = report.disagreements.find((d) => d.slug === c.slug && d.slice === c.slice); | |
| const table = dis ? dis.submissions.map((s) => | |
| `| \`${s.model}\` | **${s.grade}** | ${s.headline} | w=${s.weight} | ${s.chat_url ? `[chat](${s.chat_url})` : '—'} |` | |
| ).join('\n') : ''; | |
| return `### \`${c.slice}\` — **no consensus** (${c.submissionCount} submissions)\n\n${dis ? dis.reason : ''}\n\n| model | grade | headline | weight | chat |\n|---|---|---|---|---|\n${table}\n\nAnother submission is needed to reach consensus.`; | |
| } | |
| return `### \`${c.slice}\` — **${c.currentGrade}** (${c.strength || '—'}, ${c.submissionCount} submissions)\n\n${c.kind === 'new' ? 'First assessment has reached consensus.' : `Consensus updated from ${c.previousGrade} to ${c.currentGrade}.`}\n\nAssessment PR updates \`data/assessments/${c.slug}/${c.slice}.json\`.`; | |
| }; | |
| for (const [slug, changes] of bySlug) { | |
| const title = `[${slug}] DEFI@home`; | |
| const existing = await github.rest.search.issuesAndPullRequests({ | |
| q: `repo:${context.repo.owner}/${context.repo.repo} is:issue in:title "${title}"`, | |
| }); | |
| const found = existing.data.items.find((i) => i.title === title && i.state === 'open'); | |
| const body = changes.map(sectionFor).join('\n\n---\n\n'); | |
| const sliceLabels = changes.map((c) => `slice:${c.slice}`); | |
| const hasDisagreement = changes.some((c) => c.kind === 'disagreement'); | |
| if (found) { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: found.number, | |
| body, | |
| }); | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: found.number, | |
| labels: sliceLabels, | |
| }); | |
| if (hasDisagreement) { | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: found.number, | |
| labels: ['quorum-disagreement'], | |
| }); | |
| } else { | |
| try { | |
| await github.rest.issues.removeLabel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: found.number, | |
| name: 'quorum-disagreement', | |
| }); | |
| } catch (_) {} | |
| } | |
| } else { | |
| const labels = ['defi-at-home', ...sliceLabels]; | |
| if (hasDisagreement) labels.push('quorum-disagreement'); | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title, | |
| body, | |
| labels, | |
| }); | |
| } | |
| } | |
| - name: Open assessments PR if anything changed | |
| uses: peter-evans/create-pull-request@v7 | |
| with: | |
| commit-message: "[quorum] merge new / updated assessments" | |
| title: "[quorum] DEFI@home assessments — ${{ github.run_number }}" | |
| body: | | |
| Automated quorum merge. See workflow run for the report. | |
| branch: quorum/auto-run-${{ github.run_number }} | |
| add-paths: data/assessments/** | |
| delete-branch: true |