Mobile UX: Vocabulary page has overwhelming toolbar density on mobile #27
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: Squad Issue Assign | |
| on: | |
| issues: | |
| types: [labeled] | |
| permissions: | |
| issues: write | |
| contents: read | |
| jobs: | |
| assign-work: | |
| # Only trigger on squad:{member} labels (not the base "squad" label) | |
| if: startsWith(github.event.label.name, 'squad:') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Identify assigned member and trigger work | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const issue = context.payload.issue; | |
| const label = context.payload.label.name; | |
| // Extract member name from label (e.g., "squad:ripley" → "ripley") | |
| const memberName = label.replace('squad:', '').toLowerCase(); | |
| // Read team roster — check .squad/ first, fall back to .ai-team/ | |
| let teamFile = '.squad/team.md'; | |
| if (!fs.existsSync(teamFile)) { | |
| teamFile = '.ai-team/team.md'; | |
| } | |
| if (!fs.existsSync(teamFile)) { | |
| core.warning('No .squad/team.md or .ai-team/team.md found — cannot assign work'); | |
| return; | |
| } | |
| const content = fs.readFileSync(teamFile, 'utf8'); | |
| const lines = content.split('\n'); | |
| // Check if this is a coding agent assignment | |
| const isCopilotAssignment = memberName === 'copilot'; | |
| let assignedMember = null; | |
| if (isCopilotAssignment) { | |
| assignedMember = { name: '@copilot', role: 'Coding Agent' }; | |
| } else { | |
| let inMembersTable = false; | |
| for (const line of lines) { | |
| if (line.match(/^##\s+(Members|Team Roster)/i)) { | |
| inMembersTable = true; | |
| continue; | |
| } | |
| if (inMembersTable && line.startsWith('## ')) { | |
| break; | |
| } | |
| if (inMembersTable && line.startsWith('|') && !line.includes('---') && !line.includes('Name')) { | |
| const cells = line.split('|').map(c => c.trim()).filter(Boolean); | |
| if (cells.length >= 2 && cells[0].toLowerCase() === memberName) { | |
| assignedMember = { name: cells[0], role: cells[1] }; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| if (!assignedMember) { | |
| core.warning(`No member found matching label "${label}"`); | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| body: `⚠️ No squad member found matching label \`${label}\`. Check \`.squad/team.md\` (or \`.ai-team/team.md\`) for valid member names.` | |
| }); | |
| return; | |
| } | |
| // Post assignment acknowledgment | |
| let comment; | |
| if (isCopilotAssignment) { | |
| comment = [ | |
| `### 🤖 Routed to @copilot (Coding Agent)`, | |
| '', | |
| `**Issue:** #${issue.number} — ${issue.title}`, | |
| '', | |
| `@copilot has been assigned and will pick this up automatically.`, | |
| '', | |
| `> The coding agent will create a \`copilot/*\` branch and open a draft PR.`, | |
| `> Review the PR as you would any team member's work.`, | |
| ].join('\n'); | |
| } else { | |
| comment = [ | |
| `### 📋 Assigned to ${assignedMember.name} (${assignedMember.role})`, | |
| '', | |
| `**Issue:** #${issue.number} — ${issue.title}`, | |
| '', | |
| `${assignedMember.name} will pick this up in the next Copilot session.`, | |
| '', | |
| `> **For Copilot coding agent:** If enabled, this issue will be worked automatically.`, | |
| `> Otherwise, start a Copilot session and say:`, | |
| `> \`${assignedMember.name}, work on issue #${issue.number}\``, | |
| ].join('\n'); | |
| } | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issue.number, | |
| body: comment | |
| }); | |
| core.info(`Issue #${issue.number} assigned to ${assignedMember.name} (${assignedMember.role})`); | |
| # Separate step: assign @copilot using PAT (required for coding agent) | |
| - name: Assign @copilot coding agent | |
| if: github.event.label.name == 'squad:copilot' | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.COPILOT_ASSIGN_TOKEN }} | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const issue_number = context.payload.issue.number; | |
| // Get the default branch name (main, master, etc.) | |
| const { data: repoData } = await github.rest.repos.get({ owner, repo }); | |
| const baseBranch = repoData.default_branch; | |
| try { | |
| await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/assignees', { | |
| owner, | |
| repo, | |
| issue_number, | |
| assignees: ['copilot-swe-agent[bot]'], | |
| agent_assignment: { | |
| target_repo: `${owner}/${repo}`, | |
| base_branch: baseBranch, | |
| custom_instructions: '', | |
| custom_agent: '', | |
| model: '' | |
| }, | |
| headers: { | |
| 'X-GitHub-Api-Version': '2022-11-28' | |
| } | |
| }); | |
| core.info(`Assigned copilot-swe-agent to issue #${issue_number} (base: ${baseBranch})`); | |
| } catch (err) { | |
| core.warning(`Assignment with agent_assignment failed: ${err.message}`); | |
| // Fallback: try without agent_assignment | |
| try { | |
| await github.rest.issues.addAssignees({ | |
| owner, repo, issue_number, | |
| assignees: ['copilot-swe-agent'] | |
| }); | |
| core.info(`Fallback assigned copilot-swe-agent to issue #${issue_number}`); | |
| } catch (err2) { | |
| core.warning(`Fallback also failed: ${err2.message}`); | |
| } | |
| } |