name: Sisyphus Agent on: workflow_dispatch: inputs: prompt: description: "Custom prompt" required: false # Only issue_comment works for fork PRs (secrets available) # pull_request_review/pull_request_review_comment do NOT get secrets for fork PRs issue_comment: types: [created] jobs: agent: runs-on: ubuntu-latest # @sisyphus-dev-ai mention only (maintainers, exclude self) if: >- github.event_name == 'workflow_dispatch' || (github.event_name == 'issue_comment' && contains(github.event.comment.body || '', '@sisyphus-dev-ai') && (github.event.comment.user.login || '') != 'sisyphus-dev-ai' && contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || '')) permissions: contents: read steps: # Checkout with sisyphus-dev-ai's PAT - uses: actions/checkout@v5 with: token: ${{ secrets.GH_PAT }} fetch-depth: 0 # Git config - commits as sisyphus-dev-ai - name: Configure Git as sisyphus-dev-ai run: | git config user.name "sisyphus-dev-ai" git config user.email "sisyphus-dev-ai@users.noreply.github.com" # gh CLI auth as sisyphus-dev-ai - name: Authenticate gh CLI as sisyphus-dev-ai run: | echo "${{ secrets.GH_PAT }}" | gh auth login --with-token gh auth status - name: Ensure tmux is available (Linux) if: runner.os == 'Linux' run: | set -euo pipefail if ! command -v tmux >/dev/null 2>&1; then sudo apt-get update sudo apt-get install -y --no-install-recommends tmux fi tmux -V - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Cache Bun dependencies uses: actions/cache@v4 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- # Build local oh-my-opencode - name: Build oh-my-opencode run: | bun install bun run build # Install OpenCode + configure local plugin + auth in single step - name: Setup OpenCode with oh-my-opencode env: OPENCODE_AUTH_JSON: ${{ secrets.OPENCODE_AUTH_JSON }} ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | export PATH="$HOME/.opencode/bin:$PATH" # Install OpenCode (skip if cached) if ! command -v opencode &>/dev/null; then echo "Installing OpenCode..." curl -fsSL https://opencode.ai/install -o /tmp/opencode-install.sh # Try default installer first, fallback to pinned version if it fails if file /tmp/opencode-install.sh | grep -q "shell script\|text"; then if ! bash /tmp/opencode-install.sh 2>&1; then echo "Default installer failed, trying with pinned version..." bash /tmp/opencode-install.sh --version 1.0.204 fi else echo "Download corrupted, trying direct install with pinned version..." bash <(curl -fsSL https://opencode.ai/install) --version 1.0.204 fi fi opencode --version # Run local oh-my-opencode install (uses built dist) bun run dist/cli/index.js install --no-tui --claude=max20 --chatgpt=no --gemini=no # Override plugin to use local file reference OPENCODE_JSON=~/.config/opencode/opencode.json REPO_PATH=$(pwd) jq --arg path "file://$REPO_PATH/src/index.ts" ' .plugin = [.plugin[] | select(. != "oh-my-opencode")] + [$path] ' "$OPENCODE_JSON" > /tmp/oc.json && mv /tmp/oc.json "$OPENCODE_JSON" OPENCODE_JSON=~/.config/opencode/opencode.json jq --arg baseURL "$ANTHROPIC_BASE_URL" --arg apiKey "$ANTHROPIC_API_KEY" ' .provider.anthropic = { "name": "Anthropic", "npm": "@ai-sdk/anthropic", "options": { "baseURL": $baseURL, "apiKey": $apiKey }, "models": { "claude-opus-4-5": { "id": "claude-opus-4-5-20251101", "name": "Opus 4.5", "limit": { "context": 190000, "output": 64000 }, "options": { "effort": "high" } }, "claude-opus-4-5-high": { "id": "claude-opus-4-5-20251101", "name": "Opus 4.5 High", "limit": { "context": 190000, "output": 128000 }, "options": { "effort": "high", "thinking": { "type": "enabled", "budgetTokens": 64000 } } }, "claude-sonnet-4-5": { "id": "claude-sonnet-4-5-20250929", "name": "Sonnet 4.5", "limit": { "context": 200000, "output": 64000 } }, "claude-sonnet-4-5-high": { "id": "claude-sonnet-4-5-20250929", "name": "Sonnet 4.5 High", "limit": { "context": 200000, "output": 128000 }, "options": { "thinking": { "type": "enabled", "budgetTokens": 64000 } } }, "claude-haiku-4-5": { "id": "claude-haiku-4-5-20251001", "name": "Haiku 4.5", "limit": { "context": 200000, "output": 64000 } } } } ' "$OPENCODE_JSON" > /tmp/oc.json && mv /tmp/oc.json "$OPENCODE_JSON" OMO_JSON=~/.config/opencode/oh-my-opencode.json PROMPT_APPEND=$(cat << 'PROMPT_EOF' [CODE RED] Maximum precision required. Ultrathink before acting. YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL. TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST. ## AGENT UTILIZATION PRINCIPLES (by capability, not by name) - **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure - **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs - **Planning & Strategy**: For implementation tasks, spawn a dedicated planning agent for work breakdown (not needed for simple questions/investigations) - **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning - **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation ## EXECUTION RULES - **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each. - **PARALLEL**: Fire independent agent calls simultaneously via background_task - NEVER wait sequentially. - **BACKGROUND FIRST**: Use background_task for exploration/research agents (10+ concurrent if needed). - **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done. - **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths. ## WORKFLOW 1. Analyze the request and identify required capabilities 2. Spawn exploration/librarian agents via background_task in PARALLEL (10+ if needed) 3. Always Use Plan agent with gathered context to create detailed work breakdown 4. Execute with continuous verification against original requirements ## TDD (if test infrastructure exists) 1. Write spec (requirements) 2. Write tests (failing) 3. RED: tests fail 4. Implement minimal code 5. GREEN: tests pass 6. Refactor if needed (must stay green) 7. Next feature, repeat ## ZERO TOLERANCE FAILURES - **NO Scope Reduction**: Never make "demo", "skeleton", "simplified", "basic" versions - deliver FULL implementation - **NO MockUp Work**: When user asked you to do "port A", you must "port A", fully, 100%. No Extra feature, No reduced feature, no mock data, fully working 100% port. - **NO Partial Completion**: Never stop at 60-80% saying "you can extend this..." - finish 100% - **NO Assumed Shortcuts**: Never skip requirements you deem "optional" or "can be added later" - **NO Premature Stopping**: Never declare done until ALL TODOs are completed and verified - **NO TEST DELETION**: Never delete or skip failing tests to make the build pass. Fix the code, not the tests. THE USER ASKED FOR X. DELIVER EXACTLY X. NOT A SUBSET. NOT A DEMO. NOT A STARTING POINT. --- [analyze-mode] ANALYSIS MODE. Gather context before diving deep: CONTEXT GATHERING (parallel): - 1-2 explore agents (codebase patterns, implementations) - 1-2 librarian agents (if external library involved) - Direct tools: Grep, AST-grep, LSP for targeted searches IF COMPLEX (architecture, multi-system, debugging after 2+ failures): - Consult oracle for strategic guidance SYNTHESIZE findings before proceeding. --- ## GitHub Actions Environment You are `sisyphus-dev-ai` in GitHub Actions. ### CRITICAL: GitHub Comments = Your ONLY Output User CANNOT see console. Post everything via `gh issue comment` or `gh pr comment`. ### Comment Formatting (CRITICAL) **ALWAYS use heredoc syntax for comments containing code references, backticks, or multiline content:** ```bash gh issue comment --body "$(cat <<'EOF' Your comment with `backticks` and code references preserved here. Multiple lines work perfectly. EOF )" ``` **NEVER use direct quotes with backticks** (shell will interpret them as command substitution): ```bash # WRONG - backticks disappear: gh issue comment 123 --body "text with `code`" # CORRECT - backticks preserved: gh issue comment 123 --body "$(cat <<'EOF' text with `code` EOF )" ``` ### GitHub Markdown Rules (MUST FOLLOW) **Code blocks MUST have EXACTLY 3 backticks and language identifier:** - CORRECT: ` ```bash ` ... ` ``` ` - WRONG: ` ``` ` (no language), ` ```` ` (4 backticks), ` `` ` (2 backticks) **Every opening ` ``` ` MUST have a closing ` ``` ` on its own line:** ``` ```bash code here ``` ``` **NO trailing backticks or spaces after closing ` ``` `** **For inline code, use SINGLE backticks:** `code` not ```code``` **Lists inside code blocks break rendering - avoid them or use plain text** ### Rules - EVERY response = GitHub comment (use heredoc for proper escaping) - Code changes = PR (never push main/master) - Setup: bun install first - Acknowledge immediately, report when done ### Git Config - user.name: sisyphus-dev-ai - user.email: sisyphus-dev-ai@users.noreply.github.com PROMPT_EOF ) jq --arg append "$PROMPT_APPEND" '.agents.Sisyphus.prompt_append = $append' "$OMO_JSON" > /tmp/omo.json && mv /tmp/omo.json "$OMO_JSON" mkdir -p ~/.local/share/opencode echo "$OPENCODE_AUTH_JSON" > ~/.local/share/opencode/auth.json chmod 600 ~/.local/share/opencode/auth.json cat "$OPENCODE_JSON" # Collect context - name: Collect Context id: context env: GITHUB_TOKEN: ${{ secrets.GH_PAT }} EVENT_NAME: ${{ github.event_name }} ISSUE_NUMBER: ${{ github.event.issue.number }} COMMENT_BODY: ${{ github.event.comment.body }} COMMENT_AUTHOR: ${{ github.event.comment.user.login }} COMMENT_ID_VAL: ${{ github.event.comment.id }} REPO: ${{ github.repository }} run: | if [[ "$EVENT_NAME" == "issue_comment" ]]; then ISSUE_NUM="$ISSUE_NUMBER" AUTHOR="$COMMENT_AUTHOR" COMMENT_ID="$COMMENT_ID_VAL" # Check if PR or Issue and get title ISSUE_DATA=$(gh api "repos/$REPO/issues/${ISSUE_NUM}") TITLE=$(echo "$ISSUE_DATA" | jq -r '.title') if echo "$ISSUE_DATA" | jq -e '.pull_request' > /dev/null; then echo "type=pr" >> $GITHUB_OUTPUT echo "number=${ISSUE_NUM}" >> $GITHUB_OUTPUT else echo "type=issue" >> $GITHUB_OUTPUT echo "number=${ISSUE_NUM}" >> $GITHUB_OUTPUT fi echo "title=${TITLE}" >> $GITHUB_OUTPUT fi echo "comment<> $GITHUB_OUTPUT echo "$COMMENT_BODY" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT echo "author=$AUTHOR" >> $GITHUB_OUTPUT echo "comment_id=$COMMENT_ID" >> $GITHUB_OUTPUT # Add :eyes: reaction (as sisyphus-dev-ai) - name: Add eyes reaction if: steps.context.outputs.comment_id != '' env: GITHUB_TOKEN: ${{ secrets.GH_PAT }} run: | gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \ -X POST -f content="eyes" || true - name: Add working label if: steps.context.outputs.number != '' env: GITHUB_TOKEN: ${{ secrets.GH_PAT }} run: | gh label create "sisyphus: working" \ --repo "${{ github.repository }}" \ --color "fcf2e1" \ --description "Sisyphus is currently working on this" \ --force || true if [[ "${{ steps.context.outputs.type }}" == "pr" ]]; then gh pr edit "${{ steps.context.outputs.number }}" \ --repo "${{ github.repository }}" \ --add-label "sisyphus: working" || true else gh issue edit "${{ steps.context.outputs.number }}" \ --repo "${{ github.repository }}" \ --add-label "sisyphus: working" || true fi - name: Run oh-my-opencode env: GITHUB_TOKEN: ${{ secrets.GH_PAT }} USER_COMMENT: ${{ steps.context.outputs.comment }} COMMENT_AUTHOR: ${{ steps.context.outputs.author }} CONTEXT_TYPE: ${{ steps.context.outputs.type }} CONTEXT_NUMBER: ${{ steps.context.outputs.number }} CONTEXT_TITLE: ${{ steps.context.outputs.title }} REPO_NAME: ${{ github.repository }} DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} run: | export PATH="$HOME/.opencode/bin:$PATH" PROMPT=$(cat <<'PROMPT_EOF' [analyze-mode] ANALYSIS MODE. Gather context before diving deep: CONTEXT GATHERING (parallel): - 1-2 explore agents (codebase patterns, implementations) - 1-2 librarian agents (if external library involved) - Direct tools: Grep, AST-grep, LSP for targeted searches IF COMPLEX (architecture, multi-system, debugging after 2+ failures): - Consult oracle for strategic guidance SYNTHESIZE findings before proceeding. --- Your username is @sisyphus-dev-ai, mentioned by @AUTHOR_PLACEHOLDER in REPO_PLACEHOLDER. ## Context - Title: TITLE_PLACEHOLDER - Type: TYPE_PLACEHOLDER - Number: #NUMBER_PLACEHOLDER - Repository: REPO_PLACEHOLDER - Default Branch: BRANCH_PLACEHOLDER ## User's Request COMMENT_PLACEHOLDER --- ## CRITICAL: First Steps (MUST DO BEFORE ANYTHING ELSE) ### [CODE RED] MANDATORY CONTEXT READING - ZERO EXCEPTIONS **YOU MUST READ ALL CONTENT. NOT SOME. NOT MOST. ALL.** 1. **READ FULL CONVERSATION** - Execute ALL commands below before ANY other action: - **Issues**: `gh issue view NUMBER_PLACEHOLDER --comments` - **PRs**: Use ALL THREE commands to get COMPLETE context: ```bash gh pr view NUMBER_PLACEHOLDER --comments gh api repos/REPO_PLACEHOLDER/pulls/NUMBER_PLACEHOLDER/comments gh api repos/REPO_PLACEHOLDER/pulls/NUMBER_PLACEHOLDER/reviews ``` **WHAT TO EXTRACT FROM THE CONVERSATION:** - The ORIGINAL issue/PR description (first message) - this is often the TRUE requirement - ALL previous attempts and their outcomes - ALL decisions made and their reasoning - ALL feedback, criticism, and rejection reasons - ANY linked issues, PRs, or external references - The EXACT ask from the user who mentioned you **FAILURE TO READ EVERYTHING = GUARANTEED FAILURE** You WILL make wrong assumptions. You WILL repeat past mistakes. You WILL miss critical context. 2. **CREATE TODOS IMMEDIATELY**: Right after reading, create your todo list using todo tools. - First todo: "Summarize issue/PR context and requirements" - Break down ALL work into atomic, verifiable steps - Plan everything BEFORE starting any work --- Plan everything using todo tools. Then investigate and satisfy the request. Only if user requested to you to work explicitly, then use plan agent to plan, todo obsessively then create a PR to `BRANCH_PLACEHOLDER` branch. When done, report the result to the issue/PR with `gh issue comment NUMBER_PLACEHOLDER` or `gh pr comment NUMBER_PLACEHOLDER`. PROMPT_EOF ) PROMPT="${PROMPT//AUTHOR_PLACEHOLDER/$COMMENT_AUTHOR}" PROMPT="${PROMPT//REPO_PLACEHOLDER/$REPO_NAME}" PROMPT="${PROMPT//TYPE_PLACEHOLDER/$CONTEXT_TYPE}" PROMPT="${PROMPT//NUMBER_PLACEHOLDER/$CONTEXT_NUMBER}" PROMPT="${PROMPT//TITLE_PLACEHOLDER/$CONTEXT_TITLE}" PROMPT="${PROMPT//BRANCH_PLACEHOLDER/$DEFAULT_BRANCH}" PROMPT="${PROMPT//COMMENT_PLACEHOLDER/$USER_COMMENT}" stdbuf -oL -eL bun run dist/cli/index.js run "$PROMPT" # Push changes (as sisyphus-dev-ai) - name: Push changes if: always() env: GITHUB_TOKEN: ${{ secrets.GH_PAT }} run: | if [[ -n "$(git status --porcelain)" ]]; then git add -A git commit -m "chore: changes by sisyphus-dev-ai" || true fi BRANCH=$(git branch --show-current) if [[ "$BRANCH" != "main" && "$BRANCH" != "master" ]]; then git push origin "$BRANCH" || true fi - name: Update reaction and remove label if: always() env: GITHUB_TOKEN: ${{ secrets.GH_PAT }} run: | if [[ -n "${{ steps.context.outputs.comment_id }}" ]]; then REACTION_ID=$(gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \ --jq '.[] | select(.content == "eyes" and .user.login == "sisyphus-dev-ai") | .id' | head -1) if [[ -n "$REACTION_ID" ]]; then gh api -X DELETE "/repos/${{ github.repository }}/reactions/${REACTION_ID}" || true fi gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \ -X POST -f content="+1" || true fi if [[ -n "${{ steps.context.outputs.number }}" ]]; then if [[ "${{ steps.context.outputs.type }}" == "pr" ]]; then gh pr edit "${{ steps.context.outputs.number }}" \ --repo "${{ github.repository }}" \ --remove-label "sisyphus: working" || true else gh issue edit "${{ steps.context.outputs.number }}" \ --repo "${{ github.repository }}" \ --remove-label "sisyphus: working" || true fi fi