|
| 1 | +name: Enhancement Guide |
| 2 | + |
| 3 | +on: |
| 4 | + issues: |
| 5 | + types: [opened, labeled] |
| 6 | + |
| 7 | +permissions: |
| 8 | + issues: write |
| 9 | + contents: read |
| 10 | + |
| 11 | +jobs: |
| 12 | + guide: |
| 13 | + # Only run for issues with 'enhancement' label |
| 14 | + if: contains(github.event.issue.labels.*.name, 'enhancement') |
| 15 | + runs-on: ubuntu-latest |
| 16 | + steps: |
| 17 | + - uses: actions/checkout@v5 |
| 18 | + with: |
| 19 | + fetch-depth: 1 |
| 20 | + |
| 21 | + - name: Get issue details |
| 22 | + env: |
| 23 | + GH_TOKEN: ${{ github.token }} |
| 24 | + run: | |
| 25 | + gh issue view ${{ github.event.issue.number }} \ |
| 26 | + --repo ${{ github.repository }} \ |
| 27 | + --json title,body,labels > /tmp/issue.json |
| 28 | +
|
| 29 | + - name: Gather project context |
| 30 | + run: | |
| 31 | + # Architecture and key concepts |
| 32 | + cat CLAUDE.md > /tmp/claude-md.txt |
| 33 | +
|
| 34 | + # MDL quick reference (all current syntax) |
| 35 | + if [ -f "docs/01-project/MDL_QUICK_REFERENCE.md" ]; then |
| 36 | + cat docs/01-project/MDL_QUICK_REFERENCE.md > /tmp/mdl-reference.txt |
| 37 | + else |
| 38 | + echo "No MDL quick reference found." > /tmp/mdl-reference.txt |
| 39 | + fi |
| 40 | +
|
| 41 | + # Feature implementation pipeline |
| 42 | + if [ -f ".claude/skills/implement-mdl-feature.md" ]; then |
| 43 | + cat .claude/skills/implement-mdl-feature.md > /tmp/implement-skill.txt |
| 44 | + else |
| 45 | + echo "No implementation skill found." > /tmp/implement-skill.txt |
| 46 | + fi |
| 47 | +
|
| 48 | + # MDL syntax design guidelines |
| 49 | + if [ -f ".claude/skills/design-mdl-syntax.md" ]; then |
| 50 | + cat .claude/skills/design-mdl-syntax.md > /tmp/design-skill.txt |
| 51 | + else |
| 52 | + echo "No design skill found." > /tmp/design-skill.txt |
| 53 | + fi |
| 54 | +
|
| 55 | + # List existing skills (what features already exist) |
| 56 | + ls .claude/skills/mendix/ 2>/dev/null > /tmp/skills-list.txt || echo "none" > /tmp/skills-list.txt |
| 57 | +
|
| 58 | + # List existing doctype tests (what's already covered) |
| 59 | + ls mdl-examples/doctype-tests/ 2>/dev/null > /tmp/doctype-tests.txt || echo "none" > /tmp/doctype-tests.txt |
| 60 | +
|
| 61 | + # Current feature matrix |
| 62 | + if [ -f "docs/01-project/MDL_FEATURE_MATRIX.md" ]; then |
| 63 | + cat docs/01-project/MDL_FEATURE_MATRIX.md > /tmp/feature-matrix.txt |
| 64 | + else |
| 65 | + echo "No feature matrix found." > /tmp/feature-matrix.txt |
| 66 | + fi |
| 67 | +
|
| 68 | + - name: Build API request |
| 69 | + run: | |
| 70 | + cat > /tmp/user-prompt.txt <<'PROMPT' |
| 71 | + Analyze this enhancement request and provide an implementation guide. |
| 72 | +
|
| 73 | + ## Enhancement Request |
| 74 | + PROMPT |
| 75 | + cat /tmp/issue.json >> /tmp/user-prompt.txt |
| 76 | +
|
| 77 | + cat >> /tmp/user-prompt.txt <<'PROMPT' |
| 78 | +
|
| 79 | + ## Project Context (CLAUDE.md — architecture, key concepts, review checklist) |
| 80 | + PROMPT |
| 81 | + cat /tmp/claude-md.txt >> /tmp/user-prompt.txt |
| 82 | +
|
| 83 | + cat >> /tmp/user-prompt.txt <<'PROMPT' |
| 84 | +
|
| 85 | + ## MDL Syntax Design Guidelines |
| 86 | + PROMPT |
| 87 | + cat /tmp/design-skill.txt >> /tmp/user-prompt.txt |
| 88 | +
|
| 89 | + cat >> /tmp/user-prompt.txt <<'PROMPT' |
| 90 | +
|
| 91 | + ## Implementation Pipeline (step-by-step for new MDL features) |
| 92 | + PROMPT |
| 93 | + cat /tmp/implement-skill.txt >> /tmp/user-prompt.txt |
| 94 | +
|
| 95 | + cat >> /tmp/user-prompt.txt <<'PROMPT' |
| 96 | +
|
| 97 | + ## Current MDL Quick Reference (all existing syntax) |
| 98 | + PROMPT |
| 99 | + cat /tmp/mdl-reference.txt >> /tmp/user-prompt.txt |
| 100 | +
|
| 101 | + cat >> /tmp/user-prompt.txt <<'PROMPT' |
| 102 | +
|
| 103 | + ## Feature Matrix |
| 104 | + PROMPT |
| 105 | + cat /tmp/feature-matrix.txt >> /tmp/user-prompt.txt |
| 106 | +
|
| 107 | + cat >> /tmp/user-prompt.txt <<'PROMPT' |
| 108 | +
|
| 109 | + ## Existing skill files (features already documented) |
| 110 | + PROMPT |
| 111 | + cat /tmp/skills-list.txt >> /tmp/user-prompt.txt |
| 112 | +
|
| 113 | + cat >> /tmp/user-prompt.txt <<'PROMPT' |
| 114 | +
|
| 115 | + ## Existing doctype test scripts |
| 116 | + PROMPT |
| 117 | + cat /tmp/doctype-tests.txt >> /tmp/user-prompt.txt |
| 118 | +
|
| 119 | + # Truncate to 120k to stay within API limits |
| 120 | + if [ "$(wc -c < /tmp/user-prompt.txt)" -gt 120000 ]; then |
| 121 | + head -c 120000 /tmp/user-prompt.txt > /tmp/user-prompt-truncated.txt |
| 122 | + mv /tmp/user-prompt-truncated.txt /tmp/user-prompt.txt |
| 123 | + fi |
| 124 | +
|
| 125 | + jq -n --rawfile prompt /tmp/user-prompt.txt '{ |
| 126 | + model: "nvidia/nemotron-3-super-120b-a12b:free", |
| 127 | + messages: [ |
| 128 | + { |
| 129 | + role: "system", |
| 130 | + content: "You are an implementation guide for mxcli, a Go CLI tool that reads and modifies Mendix application projects (.mpr files) using MDL (Mendix Definition Language), a SQL-like syntax.\n\nYour job is to analyze enhancement requests and produce a practical implementation guide that helps developers (human or AI agent) implement the feature correctly.\n\nYou have deep knowledge of:\n- The full-stack MDL pipeline: ANTLR4 grammar → AST → visitor → executor → BSON writer\n- Mendix BSON serialization (storage names vs qualified names, required defaults)\n- MDL syntax design principles (reads as English, standard CRUD verbs, qualified names)\n- The PR review checklist (overlap, full-stack consistency, test coverage, security)\n\nYour response MUST include these sections:\n\n1. **Completeness Assessment** — Does the issue have enough detail? If NOT, list specific questions to ask the reporter (Mendix version? example of desired syntax? which Mendix concepts are involved?).\n\n2. **Overlap Check** — Could this already be done with existing syntax? List any existing features/skills that partially cover this.\n\n3. **Proposed MDL Syntax** — Draft the MDL syntax following design guidelines. Show 2-3 examples. If the issue already proposes syntax, evaluate it against guidelines.\n\n4. **Implementation Roadmap** — Step-by-step checklist of files to create/modify, following the full-stack pipeline. Be specific: name the actual files, functions, and patterns to follow.\n\n5. **BSON Investigation** — What BSON structures need to be understood? Suggest specific investigation steps (which reflection data to check, what to create in Studio Pro for reference).\n\n6. **Testing Strategy** — What doctype test script to add, what mx check validations to expect, what integration tests to write.\n\n7. **Gotchas & Risks** — Common pitfalls for this type of feature (storage name vs qualified name, missing BSON defaults, CE error codes to expect).\n\nKeep it practical and actionable. Reference specific files and patterns from the project context. If the enhancement is unclear, prioritize section 1 (questions) and keep other sections brief." |
| 131 | + }, |
| 132 | + { |
| 133 | + role: "user", |
| 134 | + content: $prompt |
| 135 | + } |
| 136 | + ], |
| 137 | + max_tokens: 4000, |
| 138 | + temperature: 0.3 |
| 139 | + }' > /tmp/request.json |
| 140 | +
|
| 141 | + echo "Request payload size: $(wc -c < /tmp/request.json) bytes" |
| 142 | +
|
| 143 | + - name: Call OpenRouter API |
| 144 | + env: |
| 145 | + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} |
| 146 | + run: | |
| 147 | + if [ -z "$OPENROUTER_API_KEY" ]; then |
| 148 | + echo "::warning::OPENROUTER_API_KEY secret is not set" |
| 149 | + exit 0 |
| 150 | + fi |
| 151 | +
|
| 152 | + HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/response.json -X POST \ |
| 153 | + -H "Authorization: Bearer $OPENROUTER_API_KEY" \ |
| 154 | + -H "Content-Type: application/json" \ |
| 155 | + -d @/tmp/request.json \ |
| 156 | + https://openrouter.ai/api/v1/chat/completions) |
| 157 | +
|
| 158 | + echo "HTTP status: $HTTP_CODE" |
| 159 | +
|
| 160 | + if [ "$HTTP_CODE" != "200" ]; then |
| 161 | + echo "::warning::OpenRouter API returned HTTP $HTTP_CODE" |
| 162 | + cat /tmp/response.json | head -c 1000 |
| 163 | + exit 0 |
| 164 | + fi |
| 165 | +
|
| 166 | + REVIEW=$(jq -r '.choices[0].message.content // empty' /tmp/response.json) |
| 167 | +
|
| 168 | + if [ -z "$REVIEW" ]; then |
| 169 | + echo "::warning::AI returned empty content. Response:" |
| 170 | + cat /tmp/response.json | head -c 1000 |
| 171 | + exit 0 |
| 172 | + fi |
| 173 | +
|
| 174 | + echo "$REVIEW" > /tmp/guide.txt |
| 175 | + echo "Guide generated ($(wc -c < /tmp/guide.txt) bytes)" |
| 176 | +
|
| 177 | + - name: Post guide comment |
| 178 | + env: |
| 179 | + GH_TOKEN: ${{ github.token }} |
| 180 | + run: | |
| 181 | + if [ ! -f /tmp/guide.txt ]; then |
| 182 | + echo "No guide to post." |
| 183 | + exit 0 |
| 184 | + fi |
| 185 | +
|
| 186 | + { |
| 187 | + echo "## Enhancement Implementation Guide" |
| 188 | + echo "" |
| 189 | + cat /tmp/guide.txt |
| 190 | + echo "" |
| 191 | + echo "---" |
| 192 | + echo "*Automated guide via OpenRouter — [workflow source](${{ github.server_url }}/${{ github.repository }}/blob/main/.github/workflows/ai-enhancement-guide.yml)*" |
| 193 | + } > /tmp/comment.md |
| 194 | +
|
| 195 | + gh issue comment ${{ github.event.issue.number }} \ |
| 196 | + --repo ${{ github.repository }} \ |
| 197 | + --body-file /tmp/comment.md |
0 commit comments