From c287b42da91fd1c9f02cbe170a391e9067568a0f Mon Sep 17 00:00:00 2001
From: stack72
Date: Sun, 22 Mar 2026 12:30:04 +0100
Subject: [PATCH] refactor: replace /plan workflow with /triage for issue
analysis and planning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
- Replaces the `issue-planner.yml` workflow (`/plan` + `/plan-update` commands) with a single `issue-triage.yml` workflow driven by `/triage`
- Adds a bug triage phase: Claude now traces through the codebase to confirm/deny bugs and identify root cause before producing an implementation plan
- Makes `/triage` idempotent — re-running it reads the full comment thread for operator feedback and updates the existing triage in-place, eliminating the need for a separate `/plan-update` command
- Removes duplicated code style rules from the prompt (CLAUDE.md is the source of truth) and adds missing conventions: license headers, libswamp import rule, dual output modes, design docs, integration tests
## Test plan
- [ ] Comment `/triage` on a bug report issue and verify it produces a triage analysis with root cause identification before the implementation plan
- [ ] Comment `/triage` on a feature request issue and verify it classifies correctly and produces a plan
- [ ] Leave feedback as a regular comment, then comment `/triage` again — verify it picks up the feedback and updates the existing triage comment with a revision history entry
- [ ] Verify the triage comment starts with `` marker
---
.github/workflows/issue-planner.yml | 316 ----------------------------
.github/workflows/issue-triage.yml | 235 ++++++++++++++++-----
README.md | 7 +-
3 files changed, 189 insertions(+), 369 deletions(-)
delete mode 100644 .github/workflows/issue-planner.yml
diff --git a/.github/workflows/issue-planner.yml b/.github/workflows/issue-planner.yml
deleted file mode 100644
index ea97de07..00000000
--- a/.github/workflows/issue-planner.yml
+++ /dev/null
@@ -1,316 +0,0 @@
-name: Issue Planner
-
-on:
- issue_comment:
- types: [created]
-
-permissions:
- contents: read
- issues: write
-
-jobs:
- # Initial plan creation triggered by /plan command
- create-plan:
- name: Create Implementation Plan
- runs-on: ubuntu-latest
- if: |
- github.event.issue.pull_request == null &&
- github.event.comment.body == '/plan' &&
- (
- github.event.comment.author_association == 'OWNER' ||
- github.event.comment.author_association == 'MEMBER' ||
- github.event.comment.author_association == 'COLLABORATOR'
- )
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - name: Add reaction to acknowledge
- run: |
- gh api \
- --method POST \
- "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
- -f content='eyes'
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Check for existing plan comment
- id: find-plan
- run: |
- # Find existing plan comment by looking for the marker
- PLAN_COMMENT_ID=$(gh api "/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments" \
- --jq '.[] | select(.body | contains("")) | .id' | head -1)
-
- if [ -n "$PLAN_COMMENT_ID" ]; then
- echo "found=true" >> "$GITHUB_OUTPUT"
- echo "comment_id=$PLAN_COMMENT_ID" >> "$GITHUB_OUTPUT"
- echo "Found existing plan comment: $PLAN_COMMENT_ID"
- else
- echo "found=false" >> "$GITHUB_OUTPUT"
- echo "No existing plan comment found"
- fi
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Setup Claude environment
- run: |
- mkdir -p ~/.claude
-
- - name: Generate implementation plan
- uses: anthropics/claude-code-action@v1
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- prompt: |
- REPO: ${{ github.repository }}
- ISSUE NUMBER: ${{ github.event.issue.number }}
- ISSUE TITLE: ${{ github.event.issue.title }}
- ISSUE BODY:
- ${{ github.event.issue.body }}
-
- EXISTING PLAN COMMENT ID: ${{ steps.find-plan.outputs.comment_id }}
- PLAN EXISTS: ${{ steps.find-plan.outputs.found }}
-
- CRITICAL: Before doing anything else, you MUST:
- 1. Read CLAUDE.md at the repository root - this contains mandatory project standards
- 2. Read the skills in .claude/skills/ directory, especially:
- - .claude/skills/ddd/SKILL.md for domain-driven design principles
- - .claude/skills/ddd/references/patterns.md for DDD patterns
- - Any other relevant skills for the feature being planned
-
- You MUST follow all guidelines in CLAUDE.md including:
- - TypeScript strict mode, no `any` types
- - Named exports, not default exports
- - Comprehensive unit test coverage
- - Domain-driven design principles
- - Test files live next to source files (foo.ts -> foo_test.ts)
-
- Your task is to create a detailed implementation plan for this issue. Do the following:
-
- 1. **Understand the Request**: Analyze the issue to understand what is being requested.
-
- 2. **Explore the Codebase**: Use Glob, Grep, and Read tools to explore the relevant parts of the codebase. Identify:
- - Existing code that relates to this feature
- - Patterns and conventions used in similar features
- - Files that will need to be modified or created
- - Any dependencies or constraints
-
- 3. **Create an Implementation Plan**: Write a detailed plan that includes:
- - **Summary**: A brief overview of the approach
- - **DDD Analysis**: Identify domain concepts, entities, value objects, aggregates, and services involved (per .claude/skills/ddd/)
- - **Files to Modify**: List specific files that need changes and what changes
- - **Files to Create**: List any new files needed and their purpose
- - **Implementation Steps**: Ordered steps to implement the feature, following project conventions
- - **Testing Strategy**: How to test the implementation (unit tests next to source files, using @std/assert)
- - **Code Style Checklist**: Confirm adherence to TypeScript strict mode, named exports, no `any` types
- - **Potential Challenges**: Any risks or complications to be aware of
-
- 4. **Post the Plan**: Format the plan in clear markdown with headers and bullet points.
- Be specific about file paths and code locations.
- Reference line numbers where relevant.
-
- IMPORTANT: Always start your plan with this exact HTML comment on its own line:
-
-
- Then add a header: ## Implementation Plan
-
- If PLAN EXISTS is "true", UPDATE the existing comment instead of creating a new one:
- ```
- gh api --method PATCH "/repos/${{ github.repository }}/issues/comments/${{ steps.find-plan.outputs.comment_id }}" -f body="your plan here"
- ```
-
- If PLAN EXISTS is "false", CREATE a new comment:
- ```
- gh issue comment ${{ github.event.issue.number }} --body "your plan here"
- ```
-
- The plan should be detailed enough that another developer (or Claude) could implement it.
- anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
- claude_args: |
- --model claude-opus-4-5-20251101
- --allowedTools Read,Glob,Grep,Bash(gh issue comment:*),Bash(gh api:*)
-
- - name: Add completion reaction
- if: success()
- run: |
- gh api \
- --method POST \
- "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
- -f content='rocket'
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Add failure reaction
- if: failure()
- run: |
- gh api \
- --method POST \
- "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
- -f content='confused'
- gh issue comment ${{ github.event.issue.number }} --body "Failed to generate implementation plan. Please check the workflow logs for details."
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- # Update plan based on /plan-update command with feedback
- update-plan:
- name: Update Plan with Feedback
- runs-on: ubuntu-latest
- # Run on /plan-update commands from maintainers
- if: |
- github.event.issue.pull_request == null &&
- startsWith(github.event.comment.body, '/plan-update') &&
- (
- github.event.comment.author_association == 'OWNER' ||
- github.event.comment.author_association == 'MEMBER' ||
- github.event.comment.author_association == 'COLLABORATOR'
- )
-
- steps:
- - name: Check for existing plan comment
- id: find-plan
- run: |
- # Find existing plan comment by looking for the marker
- PLAN_COMMENT_ID=$(gh api "/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments" \
- --jq '.[] | select(.body | contains("")) | .id' | head -1)
-
- if [ -n "$PLAN_COMMENT_ID" ]; then
- echo "found=true" >> "$GITHUB_OUTPUT"
- echo "comment_id=$PLAN_COMMENT_ID" >> "$GITHUB_OUTPUT"
- echo "Found existing plan comment: $PLAN_COMMENT_ID"
- else
- echo "found=false" >> "$GITHUB_OUTPUT"
- echo "No existing plan comment found, skipping"
- fi
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- # Skip all remaining steps if no plan exists
- - name: Skip if no plan exists
- if: steps.find-plan.outputs.found != 'true'
- run: |
- echo "No existing plan found, skipping feedback processing"
- exit 0
-
- - name: Checkout code
- if: steps.find-plan.outputs.found == 'true'
- uses: actions/checkout@v4
-
- - name: Add reaction to acknowledge
- if: steps.find-plan.outputs.found == 'true'
- run: |
- gh api \
- --method POST \
- "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
- -f content='eyes'
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Get existing plan content
- if: steps.find-plan.outputs.found == 'true'
- id: get-plan
- run: |
- PLAN_BODY=$(gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.find-plan.outputs.comment_id }}" --jq '.body')
- {
- echo "plan<> "$GITHUB_OUTPUT"
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Setup Claude environment
- if: steps.find-plan.outputs.found == 'true'
- run: |
- mkdir -p ~/.claude
-
- - name: Update plan with feedback
- if: steps.find-plan.outputs.found == 'true'
- uses: anthropics/claude-code-action@v1
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- prompt: |
- REPO: ${{ github.repository }}
- ISSUE NUMBER: ${{ github.event.issue.number }}
- ISSUE TITLE: ${{ github.event.issue.title }}
- ISSUE BODY:
- ${{ github.event.issue.body }}
-
- EXISTING PLAN COMMENT ID: ${{ steps.find-plan.outputs.comment_id }}
-
- EXISTING PLAN:
- ${{ steps.get-plan.outputs.plan }}
-
- USER FEEDBACK (from @${{ github.event.comment.user.login }}):
- The user commented with `/plan-update` followed by their feedback. Here is the full comment:
- ${{ github.event.comment.body }}
-
- Extract the feedback by removing the `/plan-update` prefix from the comment.
-
- CRITICAL: Before doing anything else, you MUST:
- 1. Read CLAUDE.md at the repository root - this contains mandatory project standards
- 2. Read the skills in .claude/skills/ directory, especially:
- - .claude/skills/ddd/SKILL.md for domain-driven design principles
- - .claude/skills/ddd/references/patterns.md for DDD patterns
- - Any other relevant skills for the feature being planned
-
- You MUST follow all guidelines in CLAUDE.md including:
- - TypeScript strict mode, no `any` types
- - Named exports, not default exports
- - Comprehensive unit test coverage
- - Domain-driven design principles
- - Test files live next to source files (foo.ts -> foo_test.ts)
-
- A user has provided feedback on an existing implementation plan. Your task is to:
-
- 1. **Understand the Feedback**: Analyze what the user is asking for - clarification, changes, additions, or concerns.
-
- 2. **Re-explore if Needed**: If the feedback requires investigating different parts of the codebase, use Glob, Grep, and Read tools.
-
- 3. **Update the Plan**: Revise the implementation plan to address the feedback. Keep the same structure:
- - **Summary**: A brief overview of the approach
- - **DDD Analysis**: Identify domain concepts, entities, value objects, aggregates, and services involved (per .claude/skills/ddd/)
- - **Files to Modify**: List specific files that need changes and what changes
- - **Files to Create**: List any new files needed and their purpose
- - **Implementation Steps**: Ordered steps to implement the feature, following project conventions
- - **Testing Strategy**: How to test the implementation (unit tests next to source files, using @std/assert)
- - **Code Style Checklist**: Confirm adherence to TypeScript strict mode, named exports, no `any` types
- - **Potential Challenges**: Any risks or complications to be aware of
-
- 4. **Post the Updated Plan**: UPDATE the existing plan comment (do NOT create a new one):
- ```
- gh api --method PATCH "/repos/${{ github.repository }}/issues/comments/${{ steps.find-plan.outputs.comment_id }}" -f body="your updated plan here"
- ```
-
- IMPORTANT: Always start your plan with this exact HTML comment on its own line:
-
-
- Then add a header: ## Implementation Plan
-
- At the end of the plan, add a "Revision History" section noting what changed based on the feedback.
-
- Format the plan in clear markdown. Be specific about file paths and code locations.
- anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
- claude_args: |
- --model claude-opus-4-5-20251101
- --allowedTools Read,Glob,Grep,Bash(gh api:*)
-
- - name: Add completion reaction
- if: success() && steps.find-plan.outputs.found == 'true'
- run: |
- gh api \
- --method POST \
- "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
- -f content='rocket'
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Add failure reaction
- if: failure() && steps.find-plan.outputs.found == 'true'
- run: |
- gh api \
- --method POST \
- "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
- -f content='confused'
- gh issue comment ${{ github.event.issue.number }} --body "Failed to update implementation plan. Please check the workflow logs for details."
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml
index 07a16f9b..7c770347 100644
--- a/.github/workflows/issue-triage.yml
+++ b/.github/workflows/issue-triage.yml
@@ -1,62 +1,197 @@
name: Issue Triage
on:
- issues:
- types: [opened]
+ issue_comment:
+ types: [created]
permissions:
- issues: write
contents: read
+ issues: write
jobs:
triage:
- name: Triage New Issue
+ name: Triage Issue
runs-on: ubuntu-latest
+ if: |
+ github.event.issue.pull_request == null &&
+ github.event.comment.body == '/triage' &&
+ (
+ github.event.comment.author_association == 'OWNER' ||
+ github.event.comment.author_association == 'MEMBER' ||
+ github.event.comment.author_association == 'COLLABORATOR'
+ )
+
steps:
- - name: Check if author is a maintainer
- id: check-role
- uses: actions/github-script@v7
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- const login = context.payload.issue.user.login;
- let isMaintainer = false;
- try {
- const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
- owner: context.repo.owner,
- repo: context.repo.repo,
- username: login,
- });
- core.info(`Permission level for ${login}: ${data.permission}`);
- isMaintainer = ['admin', 'write'].includes(data.permission);
- } catch (error) {
- core.info(`Could not fetch permission level for ${login}: ${error.message}`);
- }
- core.setOutput('is_maintainer', isMaintainer.toString());
-
- - name: Add needs-triage label
- if: steps.check-role.outputs.is_maintainer == 'false'
- uses: actions/github-script@v7
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- await github.rest.issues.addLabels({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.payload.issue.number,
- labels: ['needs-triage'],
- });
-
- - name: Post welcome comment
- if: steps.check-role.outputs.is_maintainer == 'false'
- uses: actions/github-script@v7
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Add reaction to acknowledge
+ run: |
+ gh api \
+ --method POST \
+ "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
+ -f content='eyes'
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Check for existing triage comment
+ id: find-triage
+ run: |
+ # Find existing triage comment by looking for the marker
+ TRIAGE_COMMENT_ID=$(gh api "/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments" \
+ --jq '.[] | select(.body | contains("")) | .id' | head -1)
+
+ if [ -n "$TRIAGE_COMMENT_ID" ]; then
+ echo "found=true" >> "$GITHUB_OUTPUT"
+ echo "comment_id=$TRIAGE_COMMENT_ID" >> "$GITHUB_OUTPUT"
+ echo "Found existing triage comment: $TRIAGE_COMMENT_ID"
+ else
+ echo "found=false" >> "$GITHUB_OUTPUT"
+ echo "No existing triage comment found"
+ fi
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Collect issue comment thread
+ id: comments
+ run: |
+ # Fetch all comments on the issue (excluding the triage comment itself
+ # and the /triage command) so Claude has full context on re-runs
+ COMMENTS=$(gh api "/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments" \
+ --jq '[.[] | select(.body | (contains("") or . == "/triage") | not) | {author: .user.login, body: .body}]')
+
+ {
+ echo "thread<> "$GITHUB_OUTPUT"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup Claude environment
+ run: |
+ mkdir -p ~/.claude
+
+ - name: Triage issue and generate plan
+ uses: anthropics/claude-code-action@v1
with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- const author = context.payload.issue.user.login;
- await github.rest.issues.createComment({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.payload.issue.number,
- body: `Hi @${author}, thanks for opening this issue!\n\nWe appreciate you taking the time to report it. A maintainer will review it as soon as possible.\n\nIn the meantime, please make sure you've included all relevant details (steps to reproduce, expected vs actual behaviour, swamp version, etc.) to help us triage it quickly.`,
- });
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ prompt: |
+ REPO: ${{ github.repository }}
+ ISSUE NUMBER: ${{ github.event.issue.number }}
+ ISSUE TITLE: ${{ github.event.issue.title }}
+ ISSUE BODY:
+ ${{ github.event.issue.body }}
+
+ EXISTING TRIAGE COMMENT ID: ${{ steps.find-triage.outputs.comment_id }}
+ TRIAGE EXISTS: ${{ steps.find-triage.outputs.found }}
+
+ COMMENT THREAD (all comments on this issue, excluding /triage commands and previous triage output):
+ ${{ steps.comments.outputs.thread }}
+
+ ---
+
+ ## Phase 0: Read Project Context
+
+ Before doing anything else, you MUST read:
+ 1. `CLAUDE.md` at the repository root — this is the source of truth for all project standards and conventions. Do NOT restate its rules in the plan; the implementer will read it too.
+ 2. `design/*.md` — read the relevant design docs to understand the architecture of the area the issue touches.
+ 3. `.claude/skills/` — list the directory and read skills relevant to the issue:
+ - Always read `.claude/skills/ddd/SKILL.md` and `.claude/skills/ddd/references/patterns.md`
+ - For bugs or "not working" issues, also read `.claude/skills/swamp-troubleshooting/SKILL.md`
+ - Read any `swamp-*` skill that covers the domain area (models, workflows, vaults, data, extensions, etc.)
+
+ ## Phase 1: Triage & Analysis
+
+ IMPORTANT: Do NOT take the issue author's claims, diagnosis, or proposed solution at face value. The issue is a starting point, not a source of truth. You MUST independently verify every claim by reading the actual code. The author may be wrong about the root cause, wrong about the expected behavior, or proposing a solution that doesn't fit the architecture. Form your own conclusions from the codebase.
+
+ Classify the issue as one of: **bug**, **feature**, or **unclear**.
+
+ If TRIAGE EXISTS is "true", a previous triage was already posted. Read the COMMENT THREAD carefully — maintainers may have left feedback, corrections, or additional context since the last triage. Factor all of this into your analysis.
+
+ ### If the issue is a bug:
+ 1. Trace through the codebase using Glob, Grep, and Read to understand the relevant code paths
+ 2. Independently determine whether the reported behavior is actually a bug or expected behavior — do not assume the author is correct
+ 3. If the author claims a root cause, verify it. They may be pointing at the wrong code or misunderstanding the flow.
+ 4. If it IS a bug, identify the actual root cause from the code — which function, module, or interaction is at fault
+ 5. If it is NOT a bug, explain why the behavior is expected and what the author may be misunderstanding
+
+ ### If the issue is a feature request:
+ 1. Understand the underlying problem the author wants solved, not just their proposed solution
+ 2. Explore how the existing codebase handles similar or adjacent functionality
+ 3. Independently evaluate whether the proposed approach (if any) fits the architecture, DDD principles, and existing patterns
+ 4. If the proposed approach is unsuitable, explain why and recommend a better alternative
+ 5. Identify the domain concepts involved using DDD principles
+
+ ### If the issue is unclear:
+ 1. Note what information is missing
+ 2. Suggest clarifying questions the maintainers should ask
+
+ ## Phase 2: Implementation Plan
+
+ If the issue is valid (confirmed bug or clear feature request), create a plan. If the issue is not a bug or is unclear, skip this phase and explain your findings instead.
+
+ The plan must include:
+ - **Summary**: Brief overview of the approach and root cause (for bugs)
+ - **DDD Analysis**: Domain concepts, entities, value objects, aggregates, and services involved (per `.claude/skills/ddd/`)
+ - **Files to Modify**: Specific files with descriptions of what changes are needed
+ - **Files to Create**: New files and their purpose
+ - **Implementation Steps**: Ordered steps following project conventions from CLAUDE.md
+ - **Testing Strategy**: Unit tests (next to source as `foo_test.ts`), integration tests (in `integration/`) where cross-component contracts change, and the CLI test initialization pattern where applicable
+ - **Verification Checklist**: The implementer must run `deno check`, `deno lint`, `deno fmt`, `deno run test`, and `deno run compile` — reference this but do not restate all of CLAUDE.md
+ - **Potential Challenges**: Risks, edge cases, or complications
+
+ Reminders for the plan:
+ - Keep the blast radius small — only touch what is necessary
+ - New `.ts`/`.tsx` files need the AGPLv3 license header (run `deno run license-headers`)
+ - CLI commands must import from `src/libswamp/mod.ts`, never internal paths
+ - Every command must support both `"log"` and `"json"` output modes
+
+ ## Phase 3: Post the Result
+
+ Format in clear markdown. Be specific about file paths and reference line numbers where relevant.
+
+ IMPORTANT: Always start your comment with this exact HTML comment on its own line:
+
+
+ Then add the appropriate header:
+ - `## Implementation Plan` for valid issues with a plan
+ - `## Triage: Not a Bug` if the reported behavior is expected
+ - `## Triage: Needs Clarification` if the issue is unclear
+
+ If TRIAGE EXISTS is "true", this is a re-triage. UPDATE the existing comment and append a **Revision History** entry at the bottom noting what changed:
+ ```
+ gh api --method PATCH "/repos/${{ github.repository }}/issues/comments/${{ steps.find-triage.outputs.comment_id }}" -f body="your plan here"
+ ```
+
+ If TRIAGE EXISTS is "false", CREATE a new comment:
+ ```
+ gh issue comment ${{ github.event.issue.number }} --body "your plan here"
+ ```
+
+ The plan should be detailed enough that another developer (or Claude) could implement it without further clarification.
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
+ claude_args: |
+ --model claude-opus-4-5-20251101
+ --allowedTools Read,Glob,Grep,Bash(gh issue comment:*),Bash(gh api:*)
+
+ - name: Add completion reaction
+ if: success()
+ run: |
+ gh api \
+ --method POST \
+ "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
+ -f content='rocket'
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Add failure reaction
+ if: failure()
+ run: |
+ gh api \
+ --method POST \
+ "/repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" \
+ -f content='confused'
+ gh issue comment ${{ github.event.issue.number }} --body "Failed to triage issue. Please check the workflow logs for details."
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/README.md b/README.md
index b935c5db..96d1ab80 100644
--- a/README.md
+++ b/README.md
@@ -162,9 +162,10 @@ development process.
1. **You file an issue** —
[bug reports and feature requests](https://github.com/systeminit/swamp/issues)
are very welcome. Be as detailed as you like.
-2. **We plan it** — A maintainer comments `/plan` on the issue and Claude
- generates a detailed implementation plan, right there in the issue thread.
- Maintainers can iterate on the plan with `/plan-update` and feedback.
+2. **We triage it** — A maintainer comments `/triage` on the issue and Claude
+ analyzes the report, confirms bugs by tracing through the codebase, and
+ generates a detailed implementation plan right in the issue thread.
+ Maintainers can leave feedback as comments and re-run `/triage` to refine.
3. **We build it** — System Initiative engineers (with AI agents under our
direct control) implement the plan, with full test coverage and code review.
4. **You get credit** — We're happy to include you as a co-author on any PR