[quality] CI E2E failures: eval_js attribute error, undefined _do_not_disturb, and steps directory ConfigError #1266
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: actionadon | |
| # actionadon — Dakota's community next-action bot. | |
| # Posts one short comment each time an issue moves to a new lifecycle stage. | |
| # Handles /claim, /unclaim, and /ready. Sweeps stale claimed issues daily. | |
| # | |
| # Lifecycle: | |
| # opened → status/discussing | |
| # status/approved (maintainer) → needs spec comment | |
| # status/queued (maintainer) → queue announcement | |
| # /claim comment → status/claimed + assigned | |
| # /ready comment (wrangler) → queued for agents | |
| # /unclaim comment → back in queue | |
| # daily sweep → unclaim issues idle > 7 days | |
| on: | |
| issues: | |
| types: [opened, labeled] | |
| issue_comment: | |
| types: [created] | |
| schedule: | |
| - cron: '0 9 * * *' | |
| permissions: | |
| issues: write | |
| pull-requests: write | |
| contents: read | |
| env: | |
| WORKFLOW_NAME: "Raptor Current" | |
| # Maintainers are implicit wranglers via their repo permissions. | |
| # This list is for additional low-barrier operators who can steer the queue. | |
| # Keep this list in sync with AGENTS.md and files/hive/hive-project.yaml.example. | |
| WRANGLERS: "castrojo,ahmedadan,alatiera,hanthor,coxde,renner0e" | |
| jobs: | |
| # ── Ensure lifecycle labels exist ───────────────────────────────────────── | |
| # Idempotent. Runs before any job that writes labels. | |
| ensure-labels: | |
| if: >- | |
| github.event_name == 'issues' || | |
| github.event_name == 'schedule' || | |
| (github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request == null && | |
| (startsWith(github.event.comment.body, '/claim') || | |
| startsWith(github.event.comment.body, '/unclaim') || | |
| startsWith(github.event.comment.body, '/ready'))) | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Create lifecycle labels | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| label() { | |
| gh label create "$1" --color "$2" --description "$3" --repo "$REPO" 2>/dev/null \ | |
| || gh label edit "$1" --color "$2" --description "$3" --repo "$REPO" 2>/dev/null \ | |
| || true | |
| } | |
| label "status/discussing" "7c83fd" "Structured issue flow in progress; not ready for the agent queue yet." | |
| label "status/approved" "2ea44f" "Approved for queue preparation; add acceptance criteria before /ready." | |
| label "status/claimed" "e8b86d" "Actively being worked by a human or agent." | |
| label "agent/blocked" "e74c3c" "Blocked and needs human input before work can continue." | |
| label "status/queued" "a467dc" "Structured issue is ready for a human or agent to claim." | |
| label "needs-human/agent-oops" "f795fe" "Agent mistake or bad automation outcome; Hive must not touch." | |
| label "flow/agent-donation" "1b7f83" "Donate agent time for a repo, issue, or PR review/report request." | |
| label "flow/project-report" "0e8a16" "Agent flow: produce a sourced project report." | |
| label "flow/issue-review" "5319e7" "Agent flow: review a linked issue and produce a sourced report." | |
| label "flow/pr-review" "fbca04" "Agent flow: review a linked pull request and produce a sourced report." | |
| label "status/triage" "e4e669" "Issue needs maintainer triage." | |
| label "pr/needs-review" "e4e669" "PR needs a maintainer review before it can move forward." | |
| label "hold" "8b949e" "Do not touch; intentionally held by humans." | |
| label "do-not-merge" "b60205" "Do not merge or automate this item." | |
| # ── New issue opened ─────────────────────────────────────────────────────── | |
| # Templates stamp labels directly (e.g. kind/bug, flow/agent-donation). | |
| # Route by those labels rather than scanning free-text body markers. | |
| on-issue-opened: | |
| if: github.event_name == 'issues' && github.event.action == 'opened' | |
| needs: ensure-labels | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Label as discussing if not already labelled | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| run: | | |
| LABELS=$(gh issue view "$ISSUE_URL" --json labels --jq '[.labels[].name] | join(",")' 2>/dev/null || echo "") | |
| # Skip if already has a lifecycle label (template stamped it) | |
| if echo "$LABELS" | grep -qE "status/|flow/agent-donation"; then | |
| exit 0 | |
| fi | |
| gh issue edit "$ISSUE_URL" --add-label "status/discussing" | |
| - name: Welcome comment (bug/feature reports) | |
| if: >- | |
| !contains(github.event.issue.labels.*.name, 'flow/agent-donation') | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| WORKFLOW_NAME: ${{ env.WORKFLOW_NAME }} | |
| run: | | |
| ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oP '\d+$') | |
| cat > /tmp/comment.md << EOF | |
| **${WORKFLOW_NAME}** — thanks for the report. | |
| A maintainer will triage this and assign it to the right area. Once a fix ships in nightly, confirm it works on your machine: | |
| \`\`\`bash | |
| ujust verify ${ISSUE_NUMBER} | |
| \`\`\` | |
| Your confirmation is what closes the loop. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| - name: Fast-track donated agent work | |
| if: contains(github.event.issue.labels.*.name, 'flow/agent-donation') | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| run: | | |
| # Detect flow from the dropdown value in the body | |
| BODY=$(gh issue view "$ISSUE_URL" --json body --jq '.body // ""') | |
| FLOW_LABEL="flow/project-report" | |
| if printf '%s\n' "$BODY" | grep -Eq 'https://[^[:space:])>]+/pull/[0-9]+'; then | |
| FLOW_LABEL="flow/pr-review" | |
| elif printf '%s\n' "$BODY" | grep -Eq 'https://[^[:space:])>]+/issues/[0-9]+'; then | |
| FLOW_LABEL="flow/issue-review" | |
| fi | |
| gh issue edit "$ISSUE_URL" \ | |
| --add-label "status/queued" \ | |
| --add-label "$FLOW_LABEL" | |
| # ── Label transitions ────────────────────────────────────────────────────── | |
| on-labeled: | |
| if: github.event_name == 'issues' && github.event.action == 'labeled' | |
| needs: ensure-labels | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Comment on status/approved | |
| if: github.event.label.name == 'status/approved' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| run: | | |
| cat << 'EOF' > /tmp/comment.md | |
| ✅ Approved. The community has found its way here. | |
| Before this goes to the build queue it needs **acceptance criteria** — the spec a contributor or agent will implement against. Add it to the issue body, then apply `status/queued` to open it up. | |
| **Wranglers:** write acceptance criteria, then comment `/ready`. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| - name: Comment on status/queued | |
| if: github.event.label.name == 'status/queued' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| run: | | |
| LABELS=$(gh issue view "$ISSUE_URL" --json labels --jq '[.labels[].name] | join(",")') | |
| if echo "$LABELS" | grep -q "flow/agent-donation"; then | |
| cat << 'EOF' > /tmp/comment.md | |
| 🐝 In the queue! Hive now has the instructions it needs for this donated agent request. | |
| **Agent workflow:** | |
| ```bash | |
| just validate # check element graph | |
| just build default # build the image | |
| just lint # bootc container lint | |
| just boot-test # confirm desktop boots | |
| ``` | |
| The issue body defines the flow: project report, issue review, or PR review. Post a sourced report comment when done, then close this issue. | |
| EOF | |
| else | |
| cat << 'EOF' > /tmp/comment.md | |
| 🐟 In the queue! This issue has a spec and is ready to build. | |
| **Contributors:** comment `/claim` to take it, then: | |
| ```bash | |
| git checkout upstream/main -b fix/this-issue | |
| # make your changes | |
| just validate # check element graph | |
| just build default # build the image | |
| just boot-test # automated smoke test (exits 0/1) | |
| just lint # bootc container lint | |
| ``` | |
| Open a PR with `Closes #NNN` when ready. | |
| **Reviewers:** after the PR merges and ships in nightly: | |
| ```bash | |
| ujust verify <issue-number> # confirm the fix on your machine | |
| ``` | |
| Read [AGENTS.md](../../blob/main/AGENTS.md) for the full workflow. | |
| EOF | |
| fi | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| # ── /claim, /unclaim, and /ready ────────────────────────────────────────── | |
| claim-handler: | |
| if: >- | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request == null && | |
| (startsWith(github.event.comment.body, '/claim') || | |
| startsWith(github.event.comment.body, '/unclaim') || | |
| startsWith(github.event.comment.body, '/ready')) | |
| needs: ensure-labels | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Resolve wrangler status | |
| id: wrangler | |
| env: | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| WRANGLERS: ${{ env.WRANGLERS }} | |
| run: | | |
| IS_WRANGLER=false | |
| for user in $(echo "$WRANGLERS" | tr ',' ' '); do | |
| if [ "$COMMENTER" = "$user" ]; then | |
| IS_WRANGLER=true | |
| break | |
| fi | |
| done | |
| echo "is_wrangler=$IS_WRANGLER" >> "$GITHUB_OUTPUT" | |
| - name: Handle /claim | |
| if: startsWith(github.event.comment.body, '/claim') | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| run: | | |
| LABELS=$(gh issue view "$ISSUE_URL" --json labels --jq '[.labels[].name] | join(",")') | |
| # Already claimed | |
| if echo "$LABELS" | grep -q "status/claimed"; then | |
| ASSIGNEE=$(gh issue view "$ISSUE_URL" --json assignees --jq '.assignees[0].login // "someone"') | |
| cat << EOF > /tmp/comment.md | |
| Already claimed by @${ASSIGNEE}. If they've gone quiet, a maintainer can \`/unclaim\` to return it to the queue. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| # Not in queue | |
| if ! echo "$LABELS" | grep -q "status/queued"; then | |
| cat << 'EOF' > /tmp/comment.md | |
| This issue isn't in the agent queue yet — it needs `status/queued` before it can be claimed. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| gh issue edit "$ISSUE_URL" --add-label "status/claimed" --remove-label "status/queued" --add-assignee "$COMMENTER" | |
| if echo "$LABELS" | grep -q "flow/agent-donation"; then | |
| cat << EOF > /tmp/comment.md | |
| 🎣 @${COMMENTER} has this one! Follow the workflow embedded in the issue, post a sourced report comment when you're done, and close this issue so Hive can move on. | |
| EOF | |
| else | |
| cat << EOF > /tmp/comment.md | |
| 🎣 @${COMMENTER} has this one! | |
| **Your workflow:** | |
| \`\`\`bash | |
| git checkout upstream/main -b fix/issue-${ISSUE_NUMBER} | |
| # implement the acceptance criteria | |
| just validate # fast graph check | |
| just build default # build the image (~1hr first time) | |
| just boot-test # confirm desktop boots (exits 0/1) | |
| just lint # bootc container lint | |
| \`\`\` | |
| Open a PR with \`Closes #${ISSUE_NUMBER}\` in the description when ready. Hit a blocker? Add \`agent/blocked\` and describe what you need. | |
| EOF | |
| fi | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| - name: Handle /ready | |
| if: startsWith(github.event.comment.body, '/ready') | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| IS_WRANGLER: ${{ steps.wrangler.outputs.is_wrangler }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| PERMISSION=$(gh api "repos/${REPO}/collaborators/${COMMENTER}/permission" \ | |
| --jq '.permission' 2>/dev/null || echo "none") | |
| HAS_WRITE=false | |
| case "$PERMISSION" in admin|maintain|write) HAS_WRITE=true ;; esac | |
| if [ "$IS_WRANGLER" != "true" ] && [ "$HAS_WRITE" = "false" ]; then | |
| cat << 'EOF' > /tmp/comment.md | |
| Only a wrangler or maintainer can move an issue into the queue with `/ready`. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| LABELS=$(gh issue view "$ISSUE_URL" --json labels --jq '[.labels[].name] | join(",")') | |
| BODY=$(gh issue view "$ISSUE_URL" --json body --jq '.body // ""') | |
| if ! echo "$LABELS" | grep -q "status/approved"; then | |
| cat << 'EOF' > /tmp/comment.md | |
| This issue needs `status/approved` before it can enter the queue. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| ACCEPTANCE_SECTION=$( | |
| printf '%s\n' "$BODY" | awk ' | |
| /^###[[:space:]]/ { | |
| if (in_section) exit | |
| if ($0 ~ /^###[[:space:]]+.*Acceptance criteria[[:space:]]*$/) { | |
| in_section=1 | |
| next | |
| } | |
| } | |
| in_section { print } | |
| ' | |
| ) | |
| if [ -z "$ACCEPTANCE_SECTION" ]; then | |
| cat << 'EOF' > /tmp/comment.md | |
| This issue needs a dedicated `### Acceptance criteria` section in the body before it can enter the queue. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| if ! printf '%s\n' "$ACCEPTANCE_SECTION" | grep -Eq '^[[:space:]]*-[[:space:]]\[( |x|X)\][[:space:]]+'; then | |
| cat << 'EOF' > /tmp/comment.md | |
| This issue needs at least one real checklist item under `### Acceptance criteria` before it can enter the queue. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| if echo "$LABELS" | grep -q "status/queued"; then | |
| cat << 'EOF' > /tmp/comment.md | |
| This issue is already in the queue and ready for a human or agent to `/claim`. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| gh issue edit "$ISSUE_URL" --add-label "status/queued" | |
| cat << 'EOF' > /tmp/comment.md | |
| In the queue. Comment `/claim` to take it. | |
| **Build and test loop:** | |
| ```bash | |
| git checkout upstream/main -b fix/this-issue | |
| just validate # element graph check | |
| just build default # build the image | |
| just boot-test # automated smoke test (exits 0 = pass) | |
| just lint # bootc container lint | |
| ``` | |
| Open a PR with `Closes #NNN` in the description. Read [AGENTS.md](../../blob/main/AGENTS.md) for the full workflow. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| - name: Handle /unclaim | |
| if: startsWith(github.event.comment.body, '/unclaim') | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ISSUE_URL: ${{ github.event.issue.html_url }} | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| REPO: ${{ github.repository }} | |
| IS_WRANGLER: ${{ steps.wrangler.outputs.is_wrangler }} | |
| run: | | |
| ASSIGNEE=$(gh issue view "$ISSUE_URL" --json assignees --jq '.assignees[0].login // ""') | |
| # Allow assignee, wrangler, or repo collaborators with write+ to unclaim | |
| PERMISSION=$(gh api "repos/${REPO}/collaborators/${COMMENTER}/permission" \ | |
| --jq '.permission' 2>/dev/null || echo "none") | |
| HAS_WRITE=false | |
| case "$PERMISSION" in admin|maintain|write) HAS_WRITE=true ;; esac | |
| if [ "$COMMENTER" != "$ASSIGNEE" ] && [ "$HAS_WRITE" = "false" ] && [ "$IS_WRANGLER" != "true" ]; then | |
| cat << EOF > /tmp/comment.md | |
| Only @${ASSIGNEE}, a wrangler, or a maintainer can unclaim this issue. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| exit 0 | |
| fi | |
| gh issue edit "$ISSUE_URL" --remove-label "status/claimed" --add-label "status/queued" | |
| if [ -n "$ASSIGNEE" ]; then | |
| gh issue edit "$ISSUE_URL" --remove-assignee "$ASSIGNEE" | |
| fi | |
| cat << 'EOF' > /tmp/comment.md | |
| Back in the queue. Comment `/claim` to pick it up. Start with `just validate` to confirm the graph is sound. | |
| EOF | |
| gh issue comment "$ISSUE_URL" --body-file /tmp/comment.md | |
| # ── Stale claim sweep ────────────────────────────────────────────────────── | |
| # Daily: find claimed issues with no update in 7 days, return to queue. | |
| stale-claim-sweep: | |
| if: github.event_name == 'schedule' | |
| needs: ensure-labels | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Unclaim stale issues | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| CUTOFF=$(date -u -d '7 days ago' '+%Y-%m-%dT%H:%M:%SZ') | |
| gh issue list --repo "$REPO" \ | |
| --label "status/claimed" \ | |
| --json number,url,updatedAt,assignees \ | |
| --jq ".[] | select(.updatedAt < \"$CUTOFF\") | .number" \ | |
| | while read -r NUMBER; do | |
| ASSIGNEE=$(gh issue view "$NUMBER" --repo "$REPO" \ | |
| --json assignees --jq '.assignees[0].login // ""') | |
| gh issue edit "$NUMBER" --repo "$REPO" --remove-label "status/claimed" --add-label "status/queued" | |
| if [ -n "$ASSIGNEE" ]; then | |
| gh issue edit "$NUMBER" --repo "$REPO" --remove-assignee "$ASSIGNEE" | |
| cat << EOF > /tmp/comment.md | |
| This issue has been claimed for 7 days with no PR activity, so it's back in the queue. | |
| @${ASSIGNEE} — if you're still working on it, just \`/claim\` again and it's yours. Otherwise anyone can pick it up: | |
| \`\`\`bash | |
| git checkout upstream/main -b fix/issue-${NUMBER} | |
| just validate && just build default && just boot-test && just lint | |
| \`\`\` | |
| EOF | |
| else | |
| cat << 'EOF' > /tmp/comment.md | |
| This issue has been claimed for 7 days with no PR activity, so it's back in the queue. Comment `/claim` to take it. | |
| EOF | |
| fi | |
| gh issue comment "$NUMBER" --repo "$REPO" --body-file /tmp/comment.md | |
| done |