Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions workflows/release-notes-generator/.ambient/ambient.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "Release Notes Generator",
"description": "Generate structured release notes from git commits and tags with AI-powered intelligent categorization guided by embedded instructions from the MCP tool",
"systemPrompt": "You are a release notes generation specialist with AI-powered intelligent categorization. You create professional, structured release notes from git commit history.\n\n## Your Role\n\nHelp users generate comprehensive release notes by:\n1. Using the MCP tool to fetch commit data AND categorization instructions\n2. **Following the tool's ai_instructions** to categorize commits intelligently\n3. **Applying the tool's guidelines** to create dynamic categories\n4. Generating markdown-formatted release notes ready for GitHub releases\n\n## Architecture (CRITICAL)\n\n**MCP Tool Provides TWO MODES**:\n\n### Mode 1: AI-Powered (formatted_output=False - DEFAULT for this workflow)\n- Raw commit data from GitHub/GitLab/local repos (hash, message, author, date, PR/MR number)\n- **Comprehensive ai_instructions field** with categorization guidance\n- Instructions include: role, task, guidelines, categorization strategy, suggested sections, output format, context understanding examples, best practices\n- **YOU analyze and categorize** commits using the tool's instructions\n\n### Mode 2: Pre-Formatted (formatted_output=True - for direct IDE usage)\n- Pre-formatted markdown with automatic categorization (10 categories with emojis)\n- Categories: Breaking Changes, Security, Features, Bug Fixes, Performance, Documentation, Refactoring, Testing, Chores, Other\n- Use this only when user explicitly requests pre-formatted output or for testing in IDEs\n- **Not recommended for this workflow** - defeats the purpose of AI-powered intelligent categorization\n\n**YOUR Responsibility (Mode 1 - Default)**:\n- **Always use formatted_output=False** (default) for AI-powered categorization\n- **Extract ai_instructions** from the tool response\n- **Follow the guidelines** provided by the tool\n- **Apply the categorization strategy** to analyze commits\n- **Use suggested sections** as guidance for categories\n- **Format according to output_format** specification\n- **Explain how you applied** the tool's instructions\n\n## How to Help Users\n\n**Gather Information**:\n- Current version tag (required)\n- Previous version tag (optional - tool auto-detects if omitted)\n- Repository URL for remote repos (GitHub/GitLab) OR repo path for local\n- GitHub/GitLab token (see Token Handling Strategy below)\n- formatted_output parameter (default: False for AI-powered mode, set True only if user requests pre-formatted output)\n\n**Output Location**: All generated files go to `artifacts/release-notes/`\n\n## Token Handling Strategy (CRITICAL)\n\nWhen user provides a **remote repository URL** (GitHub or GitLab):\n\n### Step 1: Check for ACP Integration Tokens\n```python\nimport os\ngithub_token = os.getenv('GITHUB_TOKEN') # From ACP GitHub integration\ngitlab_token = os.getenv('GITLAB_TOKEN') # From ACP GitLab integration\n```\n\n### Step 2: Decision Tree\n\n**If token found in environment:**\n- Use it automatically (no need to ask user)\n- Proceed with remote fetch\n- Example: `generate_release_notes(version='v1.0.0', repo_url='...', github_token=github_token)`\n\n**If NO token found:**\n- Ask user: \"I don't have a GitHub/GitLab token configured. Would you like to:\n 1. Provide a token (recommended for private repos and better rate limits)\n 2. Proceed without a token (works for public repos, has rate limits)\n 3. Clone the repository locally instead\"\n\n**User Response Handling:**\n- **Option 1 (Provides token)**: Use the token they provide\n- **Option 2 (No token)**: Try without token (github_token=None), may fail for private repos\n- **Option 3 (Local clone)**: Ask for local path or offer to clone the repo, then use repo_path parameter\n\n### Step 3: Handle Errors Gracefully\n\n**If remote fetch fails (401/403/404):**\n- Explain: \"Failed to access repository. This might be a private repo requiring a token.\"\n- Offer fallback: \"Would you like to provide a token or clone the repository locally?\"\n\n**If rate limit exceeded:**\n- Explain: \"GitHub API rate limit exceeded. A token would increase limits.\"\n- Offer: \"Would you like to provide a token or try again later?\"\n\n### Examples\n\n**Example 1: Token found in ACP integrations**\n```python\n# Check for token from ACP integration\ngithub_token = os.getenv('GITHUB_TOKEN')\nif github_token:\n # Use it automatically - no need to ask user\n result = await generate_release_notes(\n version='v1.0.0',\n repo_url='https://github.com/owner/repo',\n github_token=github_token\n )\n```\n\n**Example 2: No token, ask user**\n```\nYou: \"I don't have a GitHub token configured. Would you like to:\n 1. Provide a token (recommended for private repos)\n 2. Try without a token (works for public repos)\n 3. Use a local clone instead\"\n\nUser: \"Try without it\"\n\nYou: [Proceed with github_token=None]\n```\n\n**Example 3: Fallback to local**\n```\nYou: \"Failed to access the repository remotely (might be private). Would you like to clone it locally instead?\"\n\nUser: \"Yes\"\n\nYou: [Offer to clone or ask for local path, then use repo_path parameter]\n```\n\n## Process Flow\n\n1. **Gather Information**: Get version tags and repository details\n2. **Handle Authentication**: Follow Token Handling Strategy above\n3. **Call MCP Tool**: Use `generate_release_notes()` with appropriate parameters\n4. **Extract Instructions**: `instructions = result['ai_instructions']`\n5. **Read Commits**: `commits = result['data']['commits']`\n6. **Follow Instructions**: Apply guidelines, strategy, and formatting from tool\n7. **Generate Notes**: Create dynamic categories based on actual commits\n8. **Save Output**: Save to `artifacts/release-notes/RELEASE_NOTES_<version>.md`\n9. **Present Results**: Show notes and explain how you applied instructions\n\n## Using the Tool's Instructions\n\nThe tool response includes:\n```json\n{\n \"ai_instructions\": {\n \"role\": \"release_notes_categorizer\",\n \"task\": \"Analyze commits and create intelligent release notes\",\n \"guidelines\": [\n \"Create dynamic categories based on actual changes\",\n \"Group related commits intelligently\",\n \"Understand context beyond pattern matching\",\n ...\n ],\n \"categorization_strategy\": {\n \"step1\": \"Read all commits first\",\n \"step2\": \"Identify major themes\",\n \"step3\": \"Create relevant categories\",\n \"step4\": \"Group intelligently\",\n \"step5\": \"Prioritize important changes\"\n },\n \"suggested_sections\": {\n \"always_consider\": [\"Breaking Changes\", \"Security\", \"Features\", \"Bug Fixes\"],\n \"conditionally_add\": [\"Performance\", \"Documentation\", ...]\n },\n \"output_format\": {...},\n \"context_understanding\": {...},\n \"best_practices\": [...]\n }\n}\n```\n\n**How to apply:**\n1. Extract instructions from response\n2. Follow each guideline when analyzing commits\n3. Use the categorization_strategy steps\n4. Consider suggested_sections for creating categories\n5. Format output according to output_format spec\n6. Apply context_understanding examples to interpret commits\n7. Follow best_practices for presentation\n\n## Key Points\n\n- **Check for tokens from ACP integrations first** (GITHUB_TOKEN, GITLAB_TOKEN environment variables)\n- **Ask user if no token found** - don't assume, offer options\n- **Fallback to local clone** if remote access fails\n- **Instructions are in the tool response** - always extract and use them\n- **Guidelines are version-controlled with the tool** - always up to date\n- **Dynamic categorization** - create categories that fit THIS release\n- **Context understanding** - apply tool's examples to understand commits\n- **Explain your work** - tell users how you applied the instructions\n- **formatted_output parameter exists** - but don't use it for this AI workflow\n\n## Quality Guidelines\n\n- Always check for GITHUB_TOKEN or GITLAB_TOKEN environment variables first\n- Ask user for token or offer alternatives if not found\n- Handle authentication errors gracefully with fallback options\n- Always use formatted_output=False (default) for AI-powered categorization\n- Always extract and follow ai_instructions from tool response\n- Apply ALL guidelines provided by the tool\n- Use the tool's categorization strategy step-by-step\n- Consider both always_consider and conditionally_add sections\n- Format output exactly as specified in output_format\n- Explain to users how you applied the tool's instructions",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid collecting access tokens via chat text.

The prompt currently normalizes β€œprovide a token” in-conversation, which risks secret exposure in chat logs/transcripts. Require ACP integration/env vars (or secure secret input UX) and explicitly tell users not to paste raw tokens into messages.

As per coding guidelines **: "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workflows/release-notes-generator/.ambient/ambient.json` at line 4, The Token
Handling Strategy currently instructs asking users to "Provide a token" in-chat,
which risks secret leakage; update the Token Handling Strategy and all user
prompt text to forbid pasting tokens into chat and require ACP integration/env
vars (GITHUB_TOKEN, GITLAB_TOKEN) or a secure secret-input UX (or local repo
path) instead, revise examples that show user chat-provided tokens (e.g.,
generate_release_notes usage) to show using environment variables or secure UI,
and change decision-tree steps and error-handling prompts to offer secure
alternatives (set env var, use ACP integration, use secure secret dialog, or
clone locally) rather than asking for raw tokens in messages.

"startupPrompt": "Greet the user briefly as an AI-powered release notes generation assistant. Explain that the MCP tool provides not just commit data but also intelligent categorization instructions that you follow to create dynamic, context-aware release notes. Mention support for GitHub, GitLab, and local repositories. Ask what repository and version they'd like to generate release notes for. Keep it concise (2-3 sentences).",
"results": {
"Release Notes": "artifacts/release-notes/RELEASE_NOTES_*.md",
"Raw Commit Data": "artifacts/release-notes/commits_*.json"
}
}
142 changes: 142 additions & 0 deletions workflows/release-notes-generator/.claude/commands/generate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# /generate - Generate Release Notes

Generate structured release notes from git commits between two version tags with automatic categorization.

## Usage

```
/generate [current_version] [previous_version] [repo_path] [repo_url]
```

All parameters are optional - if not provided, you'll be prompted conversationally.

## Examples

```
/generate v1.0.0 v0.9.0
/generate v2.0.0 v1.9.0 /path/to/repo
/generate v1.5.0 v1.4.0 /path/to/repo https://github.com/org/repo
```

## Process

### 1. Gather Information

Collect from user (if not in command):
- Current version tag (required)
- Previous version tag (optional)
- Repository path (optional, defaults to current directory)
- Repository URL (optional, for clickable links)

### 2. Validate Environment

```bash
# Verify git repository
git -C <repo_path> status

# List and verify tags
git -C <repo_path> tag -l
git -C <repo_path> tag -l | grep -x <version>
```

### 3. Install Tool

```bash
python3 -c "import utility_mcp_server" 2>/dev/null || pip install utility-mcp-server
```

### 4. Create Generation Script

Save to `artifacts/release-notes/generate_<version>.py`:

```python
#!/usr/bin/env python3
import asyncio
import json
from pathlib import Path
from utility_mcp_server.src.tools.release_notes_tool import generate_release_notes

async def main():
# Ensure output directory exists
Path("artifacts/release-notes").mkdir(parents=True, exist_ok=True)

# Generate release notes
result = await generate_release_notes(
version="<VERSION>",
previous_version="<PREVIOUS_VERSION>",
repo_path="<REPO_PATH>",
repo_url="<REPO_URL>",
release_date=None # Uses today's date
)

if result.get("status") == "success":
# Save release notes
notes_file = "artifacts/release-notes/RELEASE_NOTES_<VERSION>.md"
with open(notes_file, "w") as f:
f.write(result["release_notes"])
print(f"βœ… Release notes saved to: {notes_file}")

# Save statistics
if "statistics" in result:
stats_file = "artifacts/release-notes/stats_<VERSION>.json"
with open(stats_file, "w") as f:
json.dump(result["statistics"], f, indent=2)
print(f"βœ… Statistics saved to: {stats_file}")

# Display release notes
print("\n" + "="*80)
print(result["release_notes"])
print("="*80 + "\n")

# Display statistics
if "statistics" in result:
print("πŸ“Š Statistics:")
for key, value in result["statistics"].items():
print(f" {key}: {value}")

return result
else:
error_msg = result.get("error", "Unknown error")
print(f"❌ Error: {error_msg}")
return result

if __name__ == "__main__":
asyncio.run(main())
```
Comment on lines +48 to +105
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | πŸ”΅ Trivial

Clarify that placeholders must be replaced.

The script template contains placeholders like <VERSION>, <PREVIOUS_VERSION>, <REPO_PATH>, and <REPO_URL> (lines 65-68, 74, 81), but there's no explicit instruction that these must be replaced with actual values. While this may be obvious in context, adding a brief comment above the script template would improve clarity.

πŸ“ Suggested documentation improvement
 ### 4. Create Generation Script
 
+Replace `<VERSION>`, `<PREVIOUS_VERSION>`, `<REPO_PATH>`, and `<REPO_URL>` with actual values.
+
 Save to `artifacts/release-notes/generate_<version>.py`:
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### 4. Create Generation Script
Save to `artifacts/release-notes/generate_<version>.py`:
```python
#!/usr/bin/env python3
import asyncio
import json
from pathlib import Path
from utility_mcp_server.src.tools.release_notes_tool import generate_release_notes
async def main():
# Ensure output directory exists
Path("artifacts/release-notes").mkdir(parents=True, exist_ok=True)
# Generate release notes
result = await generate_release_notes(
version="<VERSION>",
previous_version="<PREVIOUS_VERSION>",
repo_path="<REPO_PATH>",
repo_url="<REPO_URL>",
release_date=None # Uses today's date
)
if result.get("status") == "success":
# Save release notes
notes_file = "artifacts/release-notes/RELEASE_NOTES_<VERSION>.md"
with open(notes_file, "w") as f:
f.write(result["release_notes"])
print(f"βœ… Release notes saved to: {notes_file}")
# Save statistics
if "statistics" in result:
stats_file = "artifacts/release-notes/stats_<VERSION>.json"
with open(stats_file, "w") as f:
json.dump(result["statistics"], f, indent=2)
print(f"βœ… Statistics saved to: {stats_file}")
# Display release notes
print("\n" + "="*80)
print(result["release_notes"])
print("="*80 + "\n")
# Display statistics
if "statistics" in result:
print("πŸ“Š Statistics:")
for key, value in result["statistics"].items():
print(f" {key}: {value}")
return result
else:
error_msg = result.get("error", "Unknown error")
print(f"❌ Error: {error_msg}")
return result
if __name__ == "__main__":
asyncio.run(main())
```
### 4. Create Generation Script
Replace `<VERSION>`, `<PREVIOUS_VERSION>`, `<REPO_PATH>`, and `<REPO_URL>` with actual values.
Save to `artifacts/release-notes/generate_<version>.py`:
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workflows/release-notes-generator/.claude/commands/generate.md` around lines
48 - 105, Summary: The script template uses placeholders (<VERSION>,
<PREVIOUS_VERSION>, <REPO_PATH>, <REPO_URL>) but doesn't tell users to replace
them. Fix: add a short clarifying comment above the script (or at the top of the
main() block) that explicitly lists the placeholders (<VERSION>,
<PREVIOUS_VERSION>, <REPO_PATH>, <REPO_URL>) and instructs the user to replace
them with real values (or supply them via templating/CLI/env) before running;
reference the generate_release_notes call in main() so readers know which
parameters must be populated.


### 5. Execute

```bash
cd artifacts/release-notes && python3 generate_<version>.py
```
Comment on lines +107 to +111
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

Path inconsistency between script and execution.

The execution step changes directory to artifacts/release-notes/ before running the script, but the script itself (line 61) uses Path("artifacts/release-notes").mkdir(...) which is a relative path. If executed from within artifacts/release-notes/, this would create artifacts/release-notes/artifacts/release-notes/, causing the script to fail or write to the wrong location.

πŸ”§ Proposed fix

Either execute from the repository root:

-### 5. Execute
-
-```bash
-cd artifacts/release-notes && python3 generate_<version>.py
-```
+### 5. Execute
+
+```bash
+python3 artifacts/release-notes/generate_<version>.py
+```

Or update the script to use absolute paths or adjust for the current directory.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### 5. Execute
```bash
cd artifacts/release-notes && python3 generate_<version>.py
```
### 5. Execute
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workflows/release-notes-generator/.claude/commands/generate.md` around lines
107 - 111, The current execute step changes into artifacts/release-notes before
running generate_<version>.py, but the script itself calls
Path("artifacts/release-notes").mkdir(...) which uses a relative path and will
create nested directories; fix by either updating the execution command to run
from the repo root (use python3 artifacts/release-notes/generate_<version>.py in
the "Execute" section) or modify the script generate_<version>.py to build an
absolute path for the artifacts directory (use
Path(__file__).resolve().parent.joinpath("artifacts/release-notes") or similar
and call mkdir on that Path instead of Path("artifacts/release-notes")).


### 6. Present Results

Show the user:
1. Generated release notes (formatted)
2. Statistics summary
3. File locations
4. Next steps

## Output

Files created in `artifacts/release-notes/`:
- `RELEASE_NOTES_<version>.md` - Main release notes
- `stats_<version>.json` - Statistics
- `generate_<version>.py` - Generation script

## Error Handling

Handle gracefully:
- Tags don't exist β†’ List available tags
- No commits β†’ Explain possible causes
- Not a git repo β†’ Verify path
- Installation fails β†’ Check Python/pip

## Tips

Suggest to users:
- Use conventional commits (`feat:`, `fix:`, etc.)
- Include PR numbers in commits
- Provide repository URL for links
- Tag releases consistently
40 changes: 40 additions & 0 deletions workflows/release-notes-generator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
.venv/
ENV/
*.egg-info/
dist/
build/

# IDEs
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store

# Output artifacts (generated at runtime)
artifacts/

# Logs
*.log
.claude/logs/

# Temporary files
*.tmp
.temp/
tmp/

# Environment
.env
.env.local

# Test outputs
test-output/
202 changes: 202 additions & 0 deletions workflows/release-notes-generator/ADD_GENERATE_COMMAND.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# How to Add the /generate Command

The system has security restrictions that prevent automatic creation of files in `.claude/commands/`.

You'll need to add the command file manually. Here's how:

## Quick Method

I've created the command content for you at:
```
/workspace/artifacts/release-notes-workflow/generate_command_temp.md
```

**Simply rename and move it:**

```bash
cd /workspace/artifacts/release-notes-workflow
mv generate_command_temp.md .claude/commands/generate.md
```

## Alternative: Create Directly in Git

If you've already pushed to GitHub and are working in a clone:

```bash
cd /path/to/your/workflows-repo/workflows/release-notes-generator

# Create the file directly
cat > .claude/commands/generate.md << 'EOF'
# /generate - Generate Release Notes

Generate structured release notes from git commits between two version tags with automatic categorization.

## Usage

\`\`\`
/generate [current_version] [previous_version] [repo_path] [repo_url]
\`\`\`

All parameters are optional - if not provided, you'll be prompted conversationally.

## Examples

\`\`\`
/generate v1.0.0 v0.9.0
/generate v2.0.0 v1.9.0 /path/to/repo
/generate v1.5.0 v1.4.0 /path/to/repo https://github.com/org/repo
\`\`\`

## Process

### 1. Gather Information

Collect from user (if not in command):
- Current version tag (required)
- Previous version tag (optional)
- Repository path (optional, defaults to current directory)
- Repository URL (optional, for clickable links)

### 2. Validate Environment

\`\`\`bash
# Verify git repository
git -C <repo_path> status

# List and verify tags
git -C <repo_path> tag -l
git -C <repo_path> tag -l | grep -x <version>
\`\`\`

### 3. Install Tool

\`\`\`bash
python3 -c "import utility_mcp_server" 2>/dev/null || pip install utility-mcp-server
\`\`\`

### 4. Create Generation Script

Save to \`artifacts/release-notes/generate_<version>.py\`:

\`\`\`python
#!/usr/bin/env python3
import asyncio
import json
from pathlib import Path
from utility_mcp_server.src.tools.release_notes_tool import generate_release_notes

async def main():
# Ensure output directory exists
Path("artifacts/release-notes").mkdir(parents=True, exist_ok=True)

# Generate release notes
result = await generate_release_notes(
version="<VERSION>",
previous_version="<PREVIOUS_VERSION>",
repo_path="<REPO_PATH>",
repo_url="<REPO_URL>",
release_date=None # Uses today's date
)

if result.get("status") == "success":
# Save release notes
notes_file = "artifacts/release-notes/RELEASE_NOTES_<VERSION>.md"
with open(notes_file, "w") as f:
f.write(result["release_notes"])
print(f"βœ… Release notes saved to: {notes_file}")

# Save statistics
if "statistics" in result:
stats_file = "artifacts/release-notes/stats_<VERSION>.json"
with open(stats_file, "w") as f:
json.dump(result["statistics"], f, indent=2)
print(f"βœ… Statistics saved to: {stats_file}")

# Display release notes
print("\n" + "="*80)
print(result["release_notes"])
print("="*80 + "\n")

# Display statistics
if "statistics" in result:
print("πŸ“Š Statistics:")
for key, value in result["statistics"].items():
print(f" {key}: {value}")

return result
else:
error_msg = result.get("error", "Unknown error")
print(f"❌ Error: {error_msg}")
return result

if __name__ == "__main__":
asyncio.run(main())
\`\`\`

### 5. Execute

\`\`\`bash
cd artifacts/release-notes && python3 generate_<version>.py
\`\`\`

### 6. Present Results

Show the user:
1. Generated release notes (formatted)
2. Statistics summary
3. File locations
4. Next steps

## Output

Files created in \`artifacts/release-notes/\`:
- \`RELEASE_NOTES_<version>.md\` - Main release notes
- \`stats_<version>.json\` - Statistics
- \`generate_<version>.py\` - Generation script

## Error Handling

Handle gracefully:
- Tags don't exist β†’ List available tags
- No commits β†’ Explain possible causes
- Not a git repo β†’ Verify path
- Installation fails β†’ Check Python/pip

## Tips

Suggest to users:
- Use conventional commits (\`feat:\`, \`fix:\`, etc.)
- Include PR numbers in commits
- Provide repository URL for links
- Tag releases consistently
EOF

# Commit it
git add .claude/commands/generate.md
git commit -m "feat: Add /generate command"
```

## Verify

Check that the file was created:

```bash
ls -la .claude/commands/
cat .claude/commands/generate.md
```

## Why is this file important?

The `/generate` command allows users to invoke the release notes generation with a slash command instead of just conversational mode. It's optional but provides a nice shortcut.

**Without it**: Workflow still works conversationally
**With it**: Users can type `/generate v1.0.0 v0.9.0` for quick invocation

## Next Steps

Once you've added the command file:

1. Commit all changes
2. Push to GitHub
3. Test with Custom Workflow in ACP
4. Verify `/generate` command appears and works
Loading