feat: add markdown-validator agent and scoped-labels skill
- Add markdown-validator agent for validating Gitea issue descriptions - Add scoped-labels skill for managing exclusive labels (status::, priority::, type::) - Add init-scoped-labels.sh script to create standard label sets - Add GiteaClient methods: createLabel, updateLabel, setScopedLabel, setScopedStatus, setScopedPriority - Support exclusive labels (scoped labels) in Gitea API 1.21+ Created scoped labels: - status::new, status::planned, status::in-progress, status::review, status::testing, status::done, status::blocked, status::cancelled - priority::critical, priority::high, priority::medium, priority::low - type::bug, type::feature, type::enhancement, type::documentation, type::refactor, type::test, type::chore - size::xs, size::s, size::m, size::l, size::xl Scoped labels are mutually exclusive within their scope - applying status::in-progress automatically removes status::new
This commit is contained in:
226
.kilo/agents/markdown-validator.md
Normal file
226
.kilo/agents/markdown-validator.md
Normal file
@@ -0,0 +1,226 @@
|
||||
---
|
||||
description: Validates and corrects Markdown descriptions for Gitea issues
|
||||
mode: subagent
|
||||
model: qwen/qwen3.6-plus:free
|
||||
color: "#F97316"
|
||||
---
|
||||
|
||||
# Markdown Validator Agent
|
||||
|
||||
Validates and fixes Markdown descriptions for Gitea issues, ensuring proper formatting and structure.
|
||||
|
||||
## Role
|
||||
|
||||
You are a technical writer specializing in Markdown validation. You ensure all issue descriptions follow Gitea's Markdown specification and best practices.
|
||||
|
||||
## Input
|
||||
|
||||
- Issue title
|
||||
- Issue body/description
|
||||
- Context (what the issue is about)
|
||||
|
||||
## Validation Rules
|
||||
|
||||
### 1. Checklist Format
|
||||
|
||||
✅ Correct:
|
||||
```markdown
|
||||
## Checklist
|
||||
- [x] Completed task
|
||||
- [ ] Pending task
|
||||
- [ ] Another pending task
|
||||
```
|
||||
|
||||
❌ Incorrect:
|
||||
```markdown
|
||||
## Checklist
|
||||
[x] Completed task (missing dash)
|
||||
- [x] Completed task (missing space after bracket)
|
||||
```
|
||||
|
||||
### 2. Headers
|
||||
|
||||
✅ Correct:
|
||||
```markdown
|
||||
## Description
|
||||
Content here
|
||||
|
||||
## Technical Details
|
||||
### Backend
|
||||
Content
|
||||
|
||||
### Frontend
|
||||
Content
|
||||
```
|
||||
|
||||
❌ Incorrect:
|
||||
```markdown
|
||||
##Description (missing space)
|
||||
## Description (leading spaces)
|
||||
```
|
||||
|
||||
### 3. Code Blocks
|
||||
|
||||
✅ Correct:
|
||||
```markdown
|
||||
```typescript
|
||||
const x = 1
|
||||
```
|
||||
```
|
||||
|
||||
❌ Incorrect:
|
||||
```markdown
|
||||
``typescript (missing backticks)
|
||||
```typescript
|
||||
(no closing backticks)
|
||||
```
|
||||
|
||||
### 4. Links
|
||||
|
||||
✅ Correct:
|
||||
```markdown
|
||||
[Link text](https://example.com)
|
||||
Related to #123
|
||||
```
|
||||
|
||||
❌ Incorrect:
|
||||
```markdown
|
||||
[Link text] (https://example.com) (space in URL)
|
||||
Related to Issue #123 (use shorthand #123)
|
||||
```
|
||||
|
||||
### 5. Tables
|
||||
|
||||
✅ Correct:
|
||||
```markdown
|
||||
| Column 1 | Column 2 |
|
||||
|----------|----------|
|
||||
| Value 1 | Value 2 |
|
||||
```
|
||||
|
||||
❌ Incorrect:
|
||||
```markdown
|
||||
|Column 1|Column 2| (missing spaces)
|
||||
|----------| (missing second column)
|
||||
```
|
||||
|
||||
### 6. Lists
|
||||
|
||||
✅ Correct:
|
||||
```markdown
|
||||
- Item 1
|
||||
- Nested item
|
||||
- Item 2
|
||||
1. Numbered
|
||||
2. Nested
|
||||
```
|
||||
|
||||
❌ Incorrect:
|
||||
```markdown
|
||||
- Item 1
|
||||
- Nested item (should be indented)
|
||||
```
|
||||
|
||||
### 7. Escaping
|
||||
|
||||
- Escape `#` in non-header contexts: `\#123`
|
||||
- Escape `*` in non-bold contexts: `\*literal\*`
|
||||
- Escape backticks: `\`literal backticks\``
|
||||
|
||||
## Output Format
|
||||
|
||||
Return the corrected Markdown:
|
||||
|
||||
```markdown
|
||||
## Description
|
||||
|
||||
[Brief description of what needs to be done]
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Task 1
|
||||
- [ ] Task 2
|
||||
- [ ] Task 3
|
||||
|
||||
## Technical Details
|
||||
|
||||
[Implementation notes]
|
||||
|
||||
## Related
|
||||
|
||||
- Related to #123
|
||||
- Depends on #456
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Criterion 1
|
||||
- [ ] Criterion 2
|
||||
```
|
||||
|
||||
## Common Fixes
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| Missing newline before header | Add `\n\n` before `#` |
|
||||
| Incorrect checkbox syntax | Fix to `- [ ]` or `- [x]` |
|
||||
| Missing language in code block | Add language identifier |
|
||||
| Broken links | Fix URL format |
|
||||
| Improper nesting | Add proper indentation |
|
||||
|
||||
## Example
|
||||
|
||||
**Input:**
|
||||
```
|
||||
Title: Add authentication
|
||||
|
||||
Body:
|
||||
Add auth system
|
||||
[x] Design API
|
||||
- Implement
|
||||
[ ] Test
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```markdown
|
||||
## Description
|
||||
|
||||
Implement authentication system for the application.
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] Design API
|
||||
- [ ] Implement authentication logic
|
||||
- [ ] Write unit tests
|
||||
- [ ] Write integration tests
|
||||
- [ ] Update documentation
|
||||
|
||||
## Technical Details
|
||||
|
||||
- Use JWT for session management
|
||||
- Implement OAuth2 providers (Google, GitHub)
|
||||
- Add rate limiting for auth endpoints
|
||||
|
||||
## Related
|
||||
|
||||
- Related to #1
|
||||
- Depends on #2 (database setup)
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Users can log in with email/password
|
||||
- [ ] Users can log in via OAuth2
|
||||
- [ ] Sessions expire after 24 hours
|
||||
- [ ] Rate limiting prevents brute force
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
@markdown-validator <issue-content>
|
||||
```
|
||||
|
||||
The agent will:
|
||||
1. Parse the input Markdown
|
||||
2. Validate against Gitea specification
|
||||
3. Fix common issues automatically
|
||||
4. Return properly formatted Markdown
|
||||
198
.kilo/skills/scoped-labels/SKILL.md
Normal file
198
.kilo/skills/scoped-labels/SKILL.md
Normal file
@@ -0,0 +1,198 @@
|
||||
---
|
||||
name: scoped-labels
|
||||
description: Work with Gitea scoped labels (exclusive labels) for categorizing issues. Create, manage, and apply scoped labels like priority::high, status::new, type::bug etc.
|
||||
---
|
||||
|
||||
# Scoped Labels Skill
|
||||
|
||||
## Purpose
|
||||
|
||||
Manage Gitea scoped labels (exclusive labels) for better issue organization and pipeline workflow.
|
||||
|
||||
## What are Scoped Labels?
|
||||
|
||||
Scoped labels are labels with `::` separator that are mutually exclusive within the same scope. When you apply a scoped label, other labels in the same scope are automatically removed.
|
||||
|
||||
### Examples
|
||||
|
||||
| Scope | Labels | Behavior |
|
||||
|-------|--------|----------|
|
||||
| `status` | `status::new`, `status::in-progress`, `status::done` | Only one status at a time |
|
||||
| `priority` | `priority::critical`, `priority::high`, `priority::medium`, `priority::low` | Only one priority at a time |
|
||||
| `type` | `type::bug`, `type::feature`, `type::enhancement` | Only one type at a time |
|
||||
| `size` | `size::xs`, `size::s`, `size::m`, `size::l`, `size::xl` | Only one size at a time |
|
||||
|
||||
## API for Scoped Labels
|
||||
|
||||
### Create Scoped Label
|
||||
|
||||
```typescript
|
||||
// Create exclusive label (scoped)
|
||||
await client.createLabel({
|
||||
name: 'status::new',
|
||||
color: '0052cc',
|
||||
description: 'New issue, not started',
|
||||
exclusive: true // This makes it a scoped label
|
||||
})
|
||||
```
|
||||
|
||||
### Apply Scoped Label
|
||||
|
||||
```typescript
|
||||
// Apply scoped label (automatically removes other status:: labels)
|
||||
await client.addLabels(issueNumber, ['status::in-progress'])
|
||||
// This removes status::new if it was applied
|
||||
```
|
||||
|
||||
## Standard Label Sets
|
||||
|
||||
### Status Labels
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "status::new", "color": "0052cc", "description": "New issue", "exclusive": true },
|
||||
{ "name": "status::planned", "color": "1d76db", "description": "Planned for sprint", "exclusive": true },
|
||||
{ "name": "status::in-progress", "color": "fbca04", "description": "Work in progress", "exclusive": true },
|
||||
{ "name": "status::review", "color": "d93f0b", "description": "Under review", "exclusive": true },
|
||||
{ "name": "status::testing", "color": "d4c5f9", "description": "In testing", "exclusive": true },
|
||||
{ "name": "status::done", "color": "0e8a16", "description": "Completed", "exclusive": true },
|
||||
{ "name": "status::blocked", "color": "b60205", "description": "Blocked", "exclusive": true }
|
||||
]
|
||||
```
|
||||
|
||||
### Priority Labels
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "priority::critical", "color": "b60205", "description": "Critical priority", "exclusive": true },
|
||||
{ "name": "priority::high", "color": "d93f0b", "description": "High priority", "exclusive": true },
|
||||
{ "name": "priority::medium", "color": "fbca04", "description": "Medium priority", "exclusive": true },
|
||||
{ "name": "priority::low", "color": "0e8a16", "description": "Low priority", "exclusive": true }
|
||||
]
|
||||
```
|
||||
|
||||
### Type Labels
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "type::bug", "color": "d73a4a", "description": "Something is broken", "exclusive": true },
|
||||
{ "name": "type::feature", "color": "0e8a16", "description": "New feature", "exclusive": true },
|
||||
{ "name": "type::enhancement", "color": "a2eeef", "description": "Improvement", "exclusive": true },
|
||||
{ "name": "type::documentation", "color": "0075ca", "description": "Documentation", "exclusive": true },
|
||||
{ "name": "type::refactor", "color": "7057ff", "description": "Code refactoring", "exclusive": true },
|
||||
{ "name": "type::test", "color": "d4c5f9", "description": "Testing", "exclusive": true }
|
||||
]
|
||||
```
|
||||
|
||||
### Size Labels
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "size::xs", "color": "cfd3d7", "description": "Extra small (<1 hour)", "exclusive": true },
|
||||
{ "name": "size::s", "color": "c2e0c6", "description": "Small (1-2 hours)", "exclusive": true },
|
||||
{ "name": "size::m", "color": "fbca04", "description": "Medium (2-4 hours)", "exclusive": true },
|
||||
{ "name": "size::l", "color": "d93f0b", "description": "Large (4-8 hours)", "exclusive": true },
|
||||
{ "name": "size::xl", "color": "b60205", "description": "Extra large (>8 hours)", "exclusive": true }
|
||||
]
|
||||
```
|
||||
|
||||
### Component Labels (Non-exclusive)
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "component::api", "color": "1d76db", "description": "API related", "exclusive": false },
|
||||
{ "name": "component::ui", "color": "bfdadc", "description": "UI related", "exclusive": false },
|
||||
{ "name": "component::database", "color": "c5def5", "description": "Database related", "exclusive": false },
|
||||
{ "name": "component::auth", "color": "d4c5f9", "description": "Authentication related", "exclusive": false }
|
||||
]
|
||||
```
|
||||
|
||||
## Workflow Integration
|
||||
|
||||
### Pipeline Status Flow
|
||||
|
||||
```
|
||||
status::new → status::planned → status::in-progress → status::review → status::testing → status::done
|
||||
↓
|
||||
status::blocked
|
||||
```
|
||||
|
||||
### Usage in Pipeline
|
||||
|
||||
```typescript
|
||||
// Set initial status
|
||||
await client.addLabels(issueNumber, ['status::new', 'priority::high', 'type::feature'])
|
||||
|
||||
// Later, update status (automatic removal of old status)
|
||||
await client.addLabels(issueNumber, ['status::in-progress']) // Removes status::new
|
||||
|
||||
// Block issue
|
||||
await client.addLabels(issueNumber, ['status::blocked']) // Removes status::in-progress
|
||||
|
||||
// Complete
|
||||
await client.addLabels(issueNumber, ['status::done']) // Removes any previous status
|
||||
```
|
||||
|
||||
## Setup Script
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Create standard scoped labels
|
||||
API_URL="https://git.softuniq.eu/api/v1"
|
||||
OWNER="UniqueSoft"
|
||||
REPO="APAW"
|
||||
TOKEN=$GITEA_TOKEN
|
||||
|
||||
# Status labels
|
||||
for LABEL in 'status::new:0052cc' 'status::planned:1d76db' 'status::in-progress:fbca04' 'status::review:d93f0b' 'status::testing:d4c5f9' 'status::done:0e8a16' 'status::blocked:b60205'; do
|
||||
NAME=$(echo $LABEL | cut -d: -f1,2)
|
||||
COLOR=$(echo $LABEL | cut -d: -f3)
|
||||
curl -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"$NAME\",\"color\":\"$COLOR\",\"exclusive\":true}" \
|
||||
"$API_URL/repos/$OWNER/$REPO/labels"
|
||||
done
|
||||
|
||||
# Priority labels
|
||||
for LABEL in 'priority::critical:b60205' 'priority::high:d93f0b' 'priority::medium:fbca04' 'priority::low:0e8a16'; do
|
||||
NAME=$(echo $LABEL | cut -d: -f1,2)
|
||||
COLOR=$(echo $LABEL | cut -d: -f3)
|
||||
curl -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"$NAME\",\"color\":\"$COLOR\",\"exclusive\":true}" \
|
||||
"$API_URL/repos/$OWNER/$REPO/labels"
|
||||
done
|
||||
```
|
||||
|
||||
## Label Naming Convention
|
||||
|
||||
1. **Scope first**: `scope::value` (e.g., `status::new`)
|
||||
2. **Lowercase**: Use lowercase letters and hyphens
|
||||
3. **Descriptive**: Make the purpose clear
|
||||
4. **Color coding**: Use semantic colors
|
||||
- Red: Critical/Blocked/Bug
|
||||
- Yellow: In progress/Warning
|
||||
- Green: Done/Success
|
||||
- Blue: Information
|
||||
|
||||
## Query by Label
|
||||
|
||||
```bash
|
||||
# Find all issues with status::in-progress
|
||||
curl -s "$API_URL/repos/$OWNER/$REPO/issues?labels=status::in-progress"
|
||||
|
||||
# Find all critical bugs
|
||||
curl -s "$API_URL/repos/$OWNER/$REPO/issues?labels=priority::critical,type::bug"
|
||||
|
||||
# Find blocked issues in any status
|
||||
curl -s "$API_URL/repos/$OWNER/$REPO/issues?labels=status::blocked"
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Automatic exclusivity**: Applying `status::in-progress` removes `status::new`
|
||||
2. **Clear categorization**: Each scope represents one dimension
|
||||
3. **Better filtering**: Combine scopes for precise queries
|
||||
4. **Visual clarity**: One label per column in board view
|
||||
Reference in New Issue
Block a user