feat: add task analysis workflow and update issue management
CRITICAL: All agents MUST now: 1. Check history before starting work (git log, closed issues) 2. Create milestones for complex tasks 3. Update issue checkboxes before closing Changes: - Add .kilo/skills/task-analysis/SKILL.md - history check, milestone creation, checkbox updates - Update requirement-refiner.md - add history check and milestone creation workflow - Update release-manager.md - add mandatory checkbox updates before closing issues All agents now require: - Post comment to Gitea (MANDATORY) - Update issue checkboxes (MANDATORY) - Close issue only when all checkboxes done
This commit is contained in:
@@ -116,15 +116,6 @@ git push origin main
|
||||
git push origin main --tags # With tags
|
||||
```
|
||||
|
||||
### Merge Commands
|
||||
```bash
|
||||
git checkout main
|
||||
git merge --squash feature/branch
|
||||
git commit -m "feat: description (#issue)"
|
||||
git tag v1.2.3
|
||||
git push origin main --tags
|
||||
```
|
||||
|
||||
---
|
||||
Status: released
|
||||
Task tool with subagent_type: "evaluator" ready for performance review
|
||||
@@ -144,15 +135,128 @@ After release:
|
||||
2. Create tags and push
|
||||
3. Use Task tool with subagent_type: "evaluator" for performance review
|
||||
4. Update release notes
|
||||
5. **UPDATE ISSUE CHECKBOXES** (MANDATORY)
|
||||
6. **POST COMMENT** to Gitea (MANDATORY)
|
||||
7. **CLOSE ISSUE** when all checkboxes are done
|
||||
|
||||
## Issue Management (MANDATORY)
|
||||
|
||||
### Before Closing Issue - 3 Required Steps:
|
||||
|
||||
#### Step 1: Post Comment
|
||||
```python
|
||||
import urllib.request, json, base64
|
||||
|
||||
def post_gitea_comment(issue_number, body):
|
||||
user, pwd = "NW", "eshkink0t"
|
||||
cred = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/users/NW/tokens",
|
||||
data=json.dumps({"name": "release-mgr", "scopes": ["all"]}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {cred}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: token = json.loads(r.read())['sha1']
|
||||
req = urllib.request.Request(
|
||||
f"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues/{issue_number}/comments",
|
||||
data=json.dumps({"body": body}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='POST'
|
||||
)
|
||||
urllib.request.urlopen(req)
|
||||
```
|
||||
|
||||
#### Step 2: Update Issue Checkboxes
|
||||
```python
|
||||
import re, urllib.request, json, base64
|
||||
|
||||
def update_issue_checkboxes(issue_number):
|
||||
user, pwd = "NW", "eshkink0t"
|
||||
cred = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
||||
|
||||
# Get token
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/users/NW/tokens",
|
||||
data=json.dumps({"name": "checkboxes", "scopes": ["all"]}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {cred}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: token = json.loads(r.read())['sha1']
|
||||
|
||||
# Get current issue body
|
||||
req = urllib.request.Request(
|
||||
f"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues/{issue_number}",
|
||||
headers={'Authorization': f'token {token}'}
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: issue = json.loads(r.read())
|
||||
|
||||
# Mark ALL checkboxes as done
|
||||
body = issue['body']
|
||||
body = re.sub(r'- \[ \] ', '- [x] ', body)
|
||||
body = re.sub(r'\* \[ \] ', '* [x] ', body)
|
||||
|
||||
# Update issue
|
||||
req = urllib.request.Request(
|
||||
f"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues/{issue_number}",
|
||||
data=json.dumps({"body": body, "state": "closed"}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='PATCH'
|
||||
)
|
||||
urllib.request.urlopen(req)
|
||||
```
|
||||
|
||||
#### Step 3: Close Issue
|
||||
```python
|
||||
def close_issue(issue_number):
|
||||
user, pwd = "NW", "eshkink0t"
|
||||
cred = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/users/NW/tokens",
|
||||
data=json.dumps({"name": "close-issue", "scopes": ["all"]}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {cred}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: token = json.loads(r.read())['sha1']
|
||||
req = urllib.request.Request(
|
||||
f"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues/{issue_number}",
|
||||
data=json.dumps({"state": "closed"}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='PATCH'
|
||||
)
|
||||
urllib.request.urlopen(req)
|
||||
```
|
||||
|
||||
### Complete Workflow
|
||||
```python
|
||||
# 1. Post comment with summary
|
||||
post_gitea_comment(issue_number, "## ✅ release-manager completed\n\n**Version**: vX.Y.Z\n**Files Changed**: 5\n\n**Next**: Issue closed")
|
||||
|
||||
# 2. Update all checkboxes to [x]
|
||||
update_issue_checkboxes(issue_number)
|
||||
|
||||
# 3. Close issue
|
||||
close_issue(issue_number)
|
||||
```
|
||||
|
||||
## Git Rules from .kilo/rules/release-manager.md
|
||||
|
||||
- Only create commits when explicitly requested by the user
|
||||
- NEVER update git config
|
||||
- NEVER run destructive commands unless explicitly requested
|
||||
- NEVER skip hooks (--no-verify, --no-gpg-sign) unless requested
|
||||
- NEVER use interactive git commands (-i flag)
|
||||
- NEVER commit secrets to git repository
|
||||
- NEVER hardcode credentials
|
||||
|
||||
## Gitea Commenting (MANDATORY)
|
||||
|
||||
**You MUST post a comment to the Gitea issue after completing your work.**
|
||||
|
||||
Post a comment with:
|
||||
1. ✅ Success: What was done, files changed, duration
|
||||
1. ✅ Success: What was done, version, files changed
|
||||
2. ❌ Error: What failed, why, and blocker
|
||||
3. ❓ Question: Clarification needed with options
|
||||
|
||||
Use the `post_comment` function from `.kilo/skills/gitea-commenting/SKILL.md`.
|
||||
Use the `post_gitea_comment` function above.
|
||||
|
||||
**NO EXCEPTIONS** - Always comment to Gitea.
|
||||
**NO EXCEPTIONS** - Always comment to Gitea and update checkboxes before closing issues.
|
||||
@@ -73,6 +73,98 @@ After completing requirements:
|
||||
1. Ensure all criteria are testable
|
||||
2. Flag any unclear points for clarification
|
||||
3. Tag `@Orchestrator` with "Requirements: Ready" status
|
||||
|
||||
## Before Starting Task (MANDATORY)
|
||||
|
||||
**ALWAYS perform these checks before processing any task:**
|
||||
|
||||
### 1. History Check
|
||||
|
||||
```bash
|
||||
# Search git history for similar work
|
||||
git log --all --oneline --grep="<keyword from task>"
|
||||
git log --all --oneline -- "<file pattern>"
|
||||
|
||||
# Check closed issues for similar tasks
|
||||
curl -s "https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues?state=closed" | \
|
||||
python3 -c "import sys,json; [print(f'#{i[\"number\"]}: {i[\"title\"]}') for i in json.load(sys.stdin) if '<keyword>' in i['title'].lower()]"
|
||||
```
|
||||
|
||||
**If similar work found:**
|
||||
- Reference existing issue/commit in new issue body
|
||||
- Document what's different
|
||||
- Reuse code if applicable
|
||||
|
||||
### 2. Complexity Analysis
|
||||
|
||||
Determine if task needs milestone:
|
||||
|
||||
| Criteria | Simple | Complex |
|
||||
|----------|--------|---------|
|
||||
| Files affected | 1-2 | > 2 |
|
||||
| Components | Single | Multiple |
|
||||
| Agents needed | 1-2 | > 2 |
|
||||
| Est. time | < 1 hour | > 1 hour |
|
||||
| Dependencies | None | Has dependencies |
|
||||
|
||||
### 3. Create Milestone (for Complex Tasks)
|
||||
|
||||
If task is complex, create a milestone with subtasks:
|
||||
|
||||
```python
|
||||
import urllib.request, json, base64
|
||||
|
||||
def create_milestone_with_subtasks(title, description, subtasks):
|
||||
user, pwd = "NW", "eshkink0t"
|
||||
cred = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
||||
|
||||
# Get token
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/users/NW/tokens",
|
||||
data=json.dumps({"name": "milestone", "scopes": ["all"]}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {cred}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: token = json.loads(r.read())['sha1']
|
||||
|
||||
# Create milestone
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/milestones",
|
||||
data=json.dumps({"title": title, "description": description}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: milestone = json.loads(r.read())
|
||||
|
||||
# Create subtask issues
|
||||
for i, subtask in enumerate(subtasks, 1):
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues",
|
||||
data=json.dumps({
|
||||
"title": subtask["title"],
|
||||
"body": f"## Checklist\n{chr(10).join(['- [ ] ' + c for c in subtask['checklist']])}",
|
||||
"milestone": milestone["id"],
|
||||
"labels": ["status::new", "priority::medium"]
|
||||
}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='POST'
|
||||
)
|
||||
urllib.request.urlopen(req)
|
||||
|
||||
return milestone
|
||||
|
||||
# Usage
|
||||
create_milestone_with_subtasks(
|
||||
title="Feature: User Authentication",
|
||||
description="Implement OAuth2 authentication",
|
||||
subtasks=[
|
||||
{"title": "OAuth Client", "checklist": ["Install library", "Implement client", "Add tests"]},
|
||||
{"title": "Session Management", "checklist": ["Session store", "Token refresh", "Logout"]},
|
||||
{"title": "Integration Tests", "checklist": ["E2E tests", "Security tests"]}
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Gitea Commenting (MANDATORY)
|
||||
|
||||
**You MUST post a comment to the Gitea issue after completing your work.**
|
||||
|
||||
272
.kilo/skills/task-analysis/SKILL.md
Normal file
272
.kilo/skills/task-analysis/SKILL.md
Normal file
@@ -0,0 +1,272 @@
|
||||
# Task Analysis Skill
|
||||
|
||||
## Overview
|
||||
|
||||
Before starting any development task, agents MUST:
|
||||
|
||||
1. **Check History** - Search for similar previous work
|
||||
2. **Create Milestone** - For complex tasks, break into subtasks
|
||||
3. **Update Issue Body** - Always mark checkboxes as completed
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: History Check (MANDATORY)
|
||||
|
||||
Before writing any code:
|
||||
|
||||
```bash
|
||||
# Search git history for similar work
|
||||
git log --all --oneline --grep="<keyword>"
|
||||
git log --all --oneline -- "<file_pattern>"
|
||||
|
||||
# Search issues for similar tasks
|
||||
curl -s "https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues?state=all" | \
|
||||
python3 -c "import sys,json; [print(f\"#{i['number']}: {i['title']}\") for i in json.load(sys.stdin) if '<keyword>' in i['title'].lower()]"
|
||||
```
|
||||
|
||||
**If similar work found:**
|
||||
- Reference existing issue/commit in new work
|
||||
- Reuse code if applicable
|
||||
- Document differences
|
||||
|
||||
### Step 2: Complexity Analysis
|
||||
|
||||
Determine if task is complex (requires milestone) or simple:
|
||||
|
||||
| Criteria | Simple | Complex |
|
||||
|----------|--------|---------|
|
||||
| Files affected | 1-2 | > 2 |
|
||||
| Components | Single | Multiple |
|
||||
| Agents needed | 1-2 | > 2 |
|
||||
| Est. time | < 1 hour | > 1 hour |
|
||||
| Dependencies | None | Has dependencies |
|
||||
|
||||
### Step 3: Create Milestone (for Complex Tasks)
|
||||
|
||||
If task is complex:
|
||||
|
||||
```python
|
||||
import urllib.request, json, base64
|
||||
|
||||
def create_milestone(title, description, due_date=None):
|
||||
user, pwd = "NW", "eshkink0t"
|
||||
cred = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
||||
|
||||
# Get token
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/users/NW/tokens",
|
||||
data=json.dumps({"name": "milestone-create", "scopes": ["all"]}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {cred}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: token = json.load(r.read())['sha1']
|
||||
|
||||
# Create milestone
|
||||
data = {
|
||||
"title": title,
|
||||
"description": description
|
||||
}
|
||||
if due_date:
|
||||
data["due_on"] = due_date
|
||||
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/milestones",
|
||||
data=json.dumps(data).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: return json.load(r.read())
|
||||
|
||||
# Usage
|
||||
milestone = create_milestone(
|
||||
title="Feature: User Authentication",
|
||||
description="# Overview\nImplement user authentication with OAuth2.\n\n# Subtasks\n- [ ] OAuth client\n- [ ] Session management\n- [ ] Token refresh"
|
||||
)
|
||||
print(f"Created milestone #{milestone['id']}")
|
||||
```
|
||||
|
||||
### Step 4: Create Subtasks (for Complex Tasks)
|
||||
|
||||
Break complex task into issues:
|
||||
|
||||
```python
|
||||
def create_subtask(milestone_id, title, body, labels=None):
|
||||
user, pwd = "NW", "eshkink0t"
|
||||
cred = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
||||
|
||||
# Get token
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/users/NW/tokens",
|
||||
data=json.dumps({"name": "subtask-create", "scopes": ["all"]}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {cred}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: token = json.load(r.read())['sha1']
|
||||
|
||||
# Create issue
|
||||
data = {
|
||||
"title": title,
|
||||
"body": body,
|
||||
"milestone": milestone_id
|
||||
}
|
||||
if labels:
|
||||
data["labels"] = labels
|
||||
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues",
|
||||
data=json.dumps(data).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: return json.load(r.read())
|
||||
|
||||
# Usage
|
||||
create_subtask(
|
||||
milestone_id=44,
|
||||
title="📝 Task: OAuth2 Client Implementation",
|
||||
body="## Checklist\n- [ ] Install OAuth2 library\n- [ ] Implement client class\n- [ ] Add unit tests",
|
||||
labels=["status::new", "priority::high", "type::feature"]
|
||||
)
|
||||
```
|
||||
|
||||
### Step 5: Update Issue Body (MANDATORY)
|
||||
|
||||
When completing work on an issue, **ALWAYS**:
|
||||
|
||||
1. **Comment on the issue** (already required)
|
||||
2. **Update the issue body** to mark checkboxes as `[x]`
|
||||
|
||||
```python
|
||||
def update_issue_checkboxes(issue_number, completed_items):
|
||||
"""
|
||||
Update issue body to mark completed checkboxes.
|
||||
|
||||
Args:
|
||||
issue_number: Issue number
|
||||
completed_items: List of checkbox texts to mark as done
|
||||
"""
|
||||
user, pwd = "NW", "eshkink0t"
|
||||
cred = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
||||
|
||||
# Get token
|
||||
req = urllib.request.Request(
|
||||
"https://git.softuniq.eu/api/v1/users/NW/tokens",
|
||||
data=json.dumps({"name": "update-checkboxes", "scopes": ["all"]}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {cred}'},
|
||||
method='POST'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: token = json.loads(r.read())['sha1']
|
||||
|
||||
# Get current body
|
||||
req = urllib.request.Request(
|
||||
f"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues/{issue_number}",
|
||||
headers={'Authorization': f'token {token}'}
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: issue = json.loads(r.read())
|
||||
|
||||
# Update checkboxes
|
||||
body = issue['body']
|
||||
for item in completed_items:
|
||||
# Match both "- [ ] item" and "* [ ] item"
|
||||
import re
|
||||
body = re.sub(
|
||||
rf'([-*]) \[ \] *({re.escape(item)}.*?)(\n|$)',
|
||||
rf'\1 [x] \2\3',
|
||||
body
|
||||
)
|
||||
|
||||
# Update issue
|
||||
req = urllib.request.Request(
|
||||
f"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues/{issue_number}",
|
||||
data=json.dumps({"body": body}).encode(),
|
||||
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
|
||||
method='PATCH'
|
||||
)
|
||||
with urllib.request.urlopen(req) as r: return json.loads(r.read())
|
||||
|
||||
# Usage
|
||||
update_issue_checkboxes(9, [
|
||||
"@requirement-refiner парсит задачу в User Story",
|
||||
"@history-miner ищет похожие реализации",
|
||||
"@system-analyst создаёт архитектуру"
|
||||
])
|
||||
```
|
||||
|
||||
## Agent Rules
|
||||
|
||||
### For requirement-refiner
|
||||
|
||||
```markdown
|
||||
## Before Starting Task
|
||||
|
||||
1. Search git history: `git log --all --oneline --grep="<keywords>"`
|
||||
2. Check closed issues for similar work
|
||||
3. If similar work exists:
|
||||
- Reference existing issue in new issue
|
||||
- Document what's different
|
||||
4. Determine complexity:
|
||||
- If complex: Create milestone with subtasks
|
||||
- If simple: Proceed directly
|
||||
```
|
||||
|
||||
### For release-manager
|
||||
|
||||
```markdown
|
||||
## Before Closing Issue
|
||||
|
||||
1. COMMENT on issue with what was done
|
||||
2. UPDATE issue body to mark all `[ ]` as `[x]`
|
||||
3. CLOSE issue only when all checkboxes are done
|
||||
```
|
||||
|
||||
### For all agents
|
||||
|
||||
```markdown
|
||||
## After Completing Work
|
||||
|
||||
1. Post comment to issue (MANDATORY)
|
||||
2. Update issue body checkboxes (MANDATORY)
|
||||
3. If all checkboxes done, close issue
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Simple Task
|
||||
|
||||
User asks: "Fix typo in README"
|
||||
|
||||
1. History check: `git log --all --oneline -- README.md` → Found previous edits
|
||||
2. Complexity: Simple (1 file, 1 line)
|
||||
3. Skip milestone creation
|
||||
4. Fix typo → Comment → Update checkboxes → Close
|
||||
|
||||
### Example 2: Complex Task
|
||||
|
||||
User asks: "Add user authentication system"
|
||||
|
||||
1. History check: `git log --all --oneline --grep="auth"` → Found similar work
|
||||
2. Complexity: Complex (multiple files, multiple agents)
|
||||
3. Create milestone:
|
||||
```python
|
||||
create_milestone("Feature: User Authentication", ...)
|
||||
```
|
||||
4. Create subtasks:
|
||||
- Issue #1: OAuth2 client
|
||||
- Issue #2: Session management
|
||||
- Issue #3: Token refresh
|
||||
- Issue #4: Unit tests
|
||||
- Issue #5: Integration tests
|
||||
5. Execute each subtask
|
||||
6. Update progress in milestone
|
||||
|
||||
## Integration with Agents
|
||||
|
||||
This skill is loaded by:
|
||||
- `requirement-refiner` - On task analysis phase
|
||||
- `orchestrator` - On task routing
|
||||
- `release-manager` - On issue closing
|
||||
- All agents - On completion reporting
|
||||
|
||||
## File Location
|
||||
|
||||
`.kilo/skills/task-analysis/SKILL.md`
|
||||
Reference in New Issue
Block a user