feat: add Gitea workflow integration with quality gates and closed-loop execution

This commit is contained in:
¨NW¨
2026-04-05 01:40:26 +01:00
parent 39eeb2f35f
commit da5c365183
3 changed files with 1097 additions and 30 deletions

279
.kilo/WORKFLOW_AUDIT.md Normal file
View File

@@ -0,0 +1,279 @@
# Workflow Completeness Audit
## Summary
| Workflow | Closed Loop | Gitea Integration | Quality Gates | Error Recovery | Final Delivery |
|----------|-------------|-------------------|---------------|----------------|----------------|
| `/landing-page` | ⚠️ Partial | ⚠️ Comments only | ❌ Missing | ❌ Missing | ✅ Docs |
| `/commerce` | ⚠️ Partial | ❌ Missing | ❌ Missing | ❌ Missing | ✅ Docs |
| `/blog` | ⚠️ Partial | ❌ Missing | ❌ Missing | ❌ Missing | ✅ Docs |
| `/booking` | ⚠️ Partial | ❌ Missing | ❌ Missing | ❌ Missing | ❌ Missing |
| `/workflow` | ✅ Full | ✅ Full | ✅ Full | ✅ Full | ✅ Full |
## Issues Found
### Missing in All Business Workflows
1. **No Gitea Issue Creation** - Workflows don't create issues first
2. **No Progress Comments** - No `post_comment()` to Gitea after steps
3. **No Checkpoints** - Can skip steps without validation
4. **No Error Blocking** - Errors don't block workflow
5. **No Final Checklist** - No delivery validation before completion
## Required Additions
### For Each Workflow
Add at the start of each workflow:
```markdown
## Step 0: Gitea Issue Creation
**MANDATORY** - Create Gitea issue before any work starts.
### Implementation
1. Check if `issue` parameter provided
2. If not, create new issue with checklist
3. Post initial status comment
4. Add `status: new` label
5. Return issue number
### Code
\`\`\`python
def create_or_get_issue(project_name, workflow_type, issue=None):
if issue:
return issue
# Create issue via Gitea API
issue = gitea.create_issue(
title=f"[{workflow_type}] {project_name}",
body=generate_checklist(workflow_type),
labels=["workflow", workflow_type, "status: new"]
)
return issue.number
\`\`\`
### Checklist Template
\`\`\`markdown
## Workflow Progress
- [ ] Requirements
- [ ] Architecture
- [ ] Backend
- [ ] Frontend
- [ ] Testing
- [ ] Review
- [ ] Docker
- [ ] Documentation
- [ ] Delivery
## Quality Gates
| Gate | Status |
|------|--------|
| Requirements | ⏳ |
| Architecture | ⏳ |
| Implementation | ⏳ |
| Testing | ⏳ |
| Security | ⏳ |
| Docker | ⏳ |
| Documentation | ⏳ |
| Delivery | ⏳ |
\`\`\`
```
Add after each step:
```markdown
### Gitea Progress Comment
\`\`\`python
def post_step_comment(issue_number, step_name, result):
gitea.post_comment(issue_number, f"""## ✅ {step_name} Complete
**Duration**: {result.duration}
**Files**: {result.files}
### Gate: {step_name}
| Check | Status |
|-------|--------|
{result.checks}
**Next**: {result.next_step}
**Progress**: {result.progress}%
""")
# Update issue label
gitea.remove_label(issue_number, f"status: {prev_status}")
gitea.add_label(issue_number, f"status: {next_status}")
\`\`\`
```
Add error handling:
```markdown
### Error Handling
\`\`\`python
def handle_step_error(issue_number, step_name, error):
# BLOCK workflow - don't proceed
gitea.post_comment(issue_number, f"""## ❌ {step_name} Failed
**Error**: {error.message}
**Blocker**: {error.blocker}
### How to Fix:
1. {error.fix_step_1}
2. {error.fix_step_2}
### Cannot Proceed Until:
- [ ] Error is resolved
- [ ] Step is re-run successfully
**Workflow PAUSED** - waiting for fix.
Reply "retry" to re-run after fixing.
""")
# Add blocked label
gitea.add_label(issue_number, "status: blocked")
# Raise exception to stop workflow
raise WorkflowBlockedError(step_name, error)
\`\`\`
```
Add final delivery:
```markdown
## Final Delivery Validation
### Pre-delivery Checklist
\`\`\`python
def validate_final_delivery(project_path):
checks = [
("Source code exists", os.path.exists(f"{project_path}/src")),
("Backend builds", run("npm run build --prefix backend")),
("Frontend builds", run("npm run build --prefix frontend")),
("Tests pass", run("npm test")),
("Docker builds", run("docker-compose build")),
("Health check", check_health()),
("README exists", os.path.exists("README.md")),
("API docs exist", os.path.exists("docs/API.md")),
("Deployment guide exists", os.path.exists("docs/DEPLOYMENT.md")),
]
results = {check[0]: check[1] for check in checks}
all_passed = all(check[1] for check in checks)
if not all_passed:
failed = [c[0] for c in checks if not c[1]]
raise DeliveryError(f"Checks failed: {failed}")
return results
\`\`\`
### Delivery Comment
\`\`\`python
def post_delivery_comment(issue_number, project_name):
gitea.post_comment(issue_number, f"""## 🎉 Workflow Complete - READY FOR DELIVERY
**Project**: {project_name}
## 📦 Delivery Package
### Source Code
- Repository: UniqueSoft/APAW
- Branch: main
### Docker
- Image: {project_name}:latest
- Health: ✅ Passing
### Tests
- Unit: ✅ Passing
- Integration: ✅ Passing
- E2E: ✅ Passing
### Documentation
- ✅ README.md
- ✅ API.md
- ✅ DEPLOYMENT.md
- ✅ ADMIN.md
## 🚀 Quick Start
\`\`\`bash
docker-compose up -d
# Access: http://localhost
\`\`\`
## ✅ Client Handoff Checklist
- [x] Source code in repository
- [x] Docker builds successfully
- [x] All tests passing
- [x] Documentation complete
- [x] Client can deploy independently
**Status**: 🟢 READY FOR CLIENT DELIVERY
""")
# Close issue
gitea.close_issue(issue_number, "Workflow completed successfully")
\`\`\`
```
## Files to Update
### 1. landing-page.md
Add:
- Step 0: Issue Creation
- Gitea comments after each step
- Error handling with blocking
- Final delivery validation
### 2. commerce.md
Add:
- Step 0: Issue Creation
- Gitea comments after each step
- Error handling with blocking
- Final delivery validation
### 3. blog.md
Add:
- Step 0: Issue Creation
- Gitea comments after each step
- Error handling with blocking
- Final delivery validation
### 4. booking.md
Add:
- Step 0: Issue Creation
- Gitea comments after each step
- Error handling with blocking
- Final delivery validation
## Integration with workflow.md
The `/workflow` command orchestrates all other workflows:
```
/workflow landing-page --project_name="MySite"
/workflow commerce --project_name="MyShop"
/workflow blog --project_name="MyBlog"
/workflow booking --project_name="MySalon"
```
Each workflow MUST:
1. Accept `issue` parameter (auto-created if not provided)
2. Call `post_comment()` after each step
3. Block on errors
4. Validate final delivery
5. Close issue on completion

View File

@@ -40,9 +40,37 @@ Create a full-stack landing page CMS from HTML mockups with Node.js backend, Vue
## Overview
```
HTML Mockups → Architecture → Backend API → Vue Frontend → Admin Panel → E2E Tests → Docker → Documentation → Product
Issue Creation → Analysis → Architecture → Backend Frontend → Testing → Review → Docker → Docs → Delivery
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
Gitea #N Comment Comment Comment Comment Comment Comment Comment Comment Final
Checkpoint Checkpoint Checkpoint Checkpoint Checkpoint Checkpoint Checkpoint Checkpoint
```
## CRITICAL: Gitea Integration (MANDATORY)
This workflow REQUIRES Gitea issue tracking. No work starts without an issue.
### Pre-conditions
```python
def ensure_gitea_issue(issue_number, project_name):
"""MANDATORY: Create Gitea issue before any work"""
if not issue_number:
issue_number = create_gitea_issue(
title=f"[landing-page] {project_name}",
body=generate_workflow_checklist(),
labels=["workflow", "landing-page", "status: new"]
)
return issue_number
```
### Workflow Progress Tracking
Every step MUST post progress to Gitea:
- 🔄 START: When step begins
- ✅ SUCCESS: When step completes with validations
- ❌ ERROR: When step fails (blocks workflow)
## Technology Stack
### Frontend
@@ -75,24 +103,131 @@ HTML Mockups → Architecture → Backend API → Vue Frontend → Admin Panel
| Mobile Safari | 14+ | Full |
| Chrome Mobile | 90+ | Full |
## Step 0: Issue Creation (MANDATORY)
**This step is ALWAYS executed first. No exceptions.**
```python
import urllib.request, json, base64, os
def create_workflow_issue(project_name, mockup_dir):
"""Create Gitea issue for workflow tracking"""
# Get credentials
username = os.environ.get('GITEA_USER', 'NW')
password = os.environ.get('GITEA_PASS', 'eshkink0t')
credentials = base64.b64encode(f"{username}:{password}".encode()).decode()
# Create token
token_req = urllib.request.Request(
"https://git.softuniq.eu/api/v1/users/NW/tokens",
data=json.dumps({"name": f"landing-{os.getpid()}", "scopes": ["all"]}).encode(),
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {credentials}'},
method='POST'
)
with urllib.request.urlopen(token_req) as r:
token = json.loads(r.read())['sha1']
# Create issue
body = f"""## Landing Page CMS Workflow
**Project**: {project_name}
**Mockups**: {mockup_dir}
## Workflow Progress
| Step | Status | Agent | Duration |
|------|--------|-------|----------|
| 0. Issue Creation | ✅ | - | - |
| 1. Analysis | ⏳ | @frontend-developer | - |
| 2. Architecture | ⏳ | @system-analyst | - |
| 3. Backend | ⏳ | @backend-developer | - |
| 4. Frontend | ⏳ | @frontend-developer | - |
| 5. Admin Panel | ⏳ | @frontend-developer | - |
| 6. Testing | ⏳ | @sdet-engineer | - |
| 7. Review | ⏳ | @code-skeptic, @security-auditor | - |
| 8. Docker | ⏳ | @release-manager | - |
| 9. Documentation | ⏳ | @system-analyst | - |
| 10. Delivery | ⏳ | @evaluator | - |
## Quality Gates
| Gate | Status | Score |
|------|--------|-------|
| Requirements | ⏳ | - |
| Architecture | ⏳ | - |
| Implementation | ⏳ | - |
| Testing | ⏳ | - |
| Security | ⏳ | - |
| Docker | ⏳ | - |
| Documentation | ⏳ | - |
| Delivery | ⏳ | - |
## Checklist
- [ ] Mockups analyzed
- [ ] Architecture designed
- [ ] Backend API implemented
- [ ] Frontend built
- [ ] Admin panel created
- [ ] Tests passing
- [ ] Code reviewed
- [ ] Docker ready
- [ ] Documentation complete
- [ ] Client delivery ready
"""
issue_req = urllib.request.Request(
"https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW/issues",
data=json.dumps({
"title": f"[landing-page] {project_name}",
"body": body,
"labels": ["workflow", "landing-page", "status: new"]
}).encode(),
headers={'Content-Type': 'application/json', 'Authorization': f'token {token}'},
method='POST'
)
with urllib.request.urlopen(issue_req) as r:
issue = json.loads(r.read())
return issue['number']
```
**Result**: Issue number for tracking all subsequent steps.
## Step 1: Analyze Mockups
**Agent**: `@FrontendDeveloper`
**Pre-condition**: Issue created (Step 0 complete)
### Input Analysis
### Execution
1. Scan mockup directory:
1. Post START to Gitea:
```python
post_comment(issue_number, f"""## 🔄 Analysis Started
**Agent**: @frontend-developer
**Step**: 1/10
**Time**: {timestamp()}
**Input**: {mockup_dir}
Analyzing HTML mockups...
""")
```
2. Scan mockup directory:
```bash
find {mockup_dir} -name "*.html" -o -name "*.htm" | head -20
```
2. Extract content structure:
3. Extract content structure:
- Public pages (home, about, contact)
- Content sections (hero, features, pricing, testimonials, footer)
- Editable content areas (text, images, CTAs)
- Forms (contact, newsletter, lead capture)
3. Create content model:
4. Create content model:
```markdown
## Content Model
@@ -107,34 +242,72 @@ HTML Mockups → Architecture → Backend API → Vue Frontend → Admin Panel
- Pricing: [{name, price, features, highlight}]
- Testimonials: [{avatar, name, role, text}]
- Footer: copyright, social_links, contact_info
### Dynamic Content
- Blog/News posts
- FAQ items
- Team members
- Portfolio items
### Forms
- Contact: name, email, phone, message
- Newsletter: email
- Lead capture: name, email, phone, interest
```
4. Post analysis to Gitea:
```python
post_gitea_comment(issue_number, """## 🎨 Mockup Analysis Complete
**Pages Identified**: {page_count}
**Content Sections**: {section_count}
**Editable Areas**: {editable_count}
**Forms Detected**: {form_count}
### Content Model
{content_model_summary}
**Next**: Architecture design
""")
5. Save artifacts:
```
.workflow/analysis/content-model.md
.workflow/analysis/pages-summary.md
```
6. Validate artifacts exist
7. Post SUCCESS to Gitea:
```python
post_comment(issue_number, f"""## ✅ Analysis Complete
**Duration**: {duration()}
**Files Scanned**: {file_count}
### Content Model
- **Pages**: {page_count}
- **Sections**: {section_count}
- **Editable Areas**: {editable_count}
- **Forms**: {form_count}
### Artifacts
- `.workflow/analysis/content-model.md`
- `.workflow/analysis/pages-summary.md`
### Gate: Analysis
| Check | Status |
|-------|--------|
| Mockups found | ✅ |
| Content model created | ✅ |
| Artifacts saved | ✅ |
**Next**: Architecture design
**Progress**: 10%
""")
update_issue_label(issue_number, "status: analysis", "status: architecture")
```
### Error Handling
```python
if error:
post_comment(issue_number, f"""## ❌ Analysis Failed
**Error**: {error_message}
**Blocker**: {blocker_description}
### How to Fix:
1. Ensure mockups directory exists: `{mockup_dir}`
2. Check HTML files are valid
3. Verify file permissions
### Cannot Proceed Until:
- [ ] Mockups directory exists
- [ ] HTML files are readable
- [ ] Content structure identified
**Workflow PAUSED**. Reply "retry" after fixing.
""")
add_label(issue_number, "status: blocked")
raise WorkflowBlockedError("Analysis failed")
```
## Step 2: Architecture Design

View File

@@ -0,0 +1,615 @@
---
name: gitea-workflow
description: Gitea integration for all workflows - issue creation, progress tracking, quality gates, final delivery
---
# Gitea Workflow Integration
Mandatory Gitea integration for ALL workflows. Ensures closed-loop execution, no partial results, complete delivery.
## Core Functions
### Create Issue
```python
import urllib.request, json, base64, os, time
GITEA_URL = "https://git.softuniq.eu"
GITEA_USER = os.environ.get('GITEA_USER', 'NW')
GITEA_PASS = os.environ.get('GITEA_PASS', 'eshkink0t')
class GiteaClient:
def __init__(self):
self.token = self._get_token()
def _get_token(self):
"""Get or create API token"""
credentials = base64.b64encode(f"{GITEA_USER}:{GITEA_PASS}".encode()).decode()
req = urllib.request.Request(
f"{GITEA_URL}/api/v1/users/{GITEA_USER}/tokens",
data=json.dumps({"name": f"workflow-{int(time.time())}", "scopes": ["all"]}).encode(),
headers={'Content-Type': 'application/json', 'Authorization': f'Basic {credentials}'},
method='POST'
)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())['sha1']
def create_issue(self, repo, title, body, labels):
"""Create workflow issue"""
url = f"{GITEA_URL}/api/v1/repos/{repo}/issues"
req = urllib.request.Request(
url,
data=json.dumps({
"title": title,
"body": body,
"labels": labels
}).encode(),
headers={
'Content-Type': 'application/json',
'Authorization': f'token {self.token}'
},
method='POST'
)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
def post_comment(self, repo, issue_number, body):
"""Post progress comment"""
url = f"{GITEA_URL}/api/v1/repos/{repo}/issues/{issue_number}/comments"
req = urllib.request.Request(
url,
data=json.dumps({"body": body}).encode(),
headers={
'Content-Type': 'application/json',
'Authorization': f'token {self.token}'
},
method='POST'
)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
def add_label(self, repo, issue_number, label):
"""Add label to issue"""
url = f"{GITEA_URL}/api/v1/repos/{repo}/issues/{issue_number}/labels"
req = urllib.request.Request(
url,
data=json.dumps({"labels": [label]}).encode(),
headers={
'Content-Type': 'application/json',
'Authorization': f'token {self.token}'
},
method='POST'
)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
def close_issue(self, repo, issue_number, comment):
"""Close issue with final comment"""
self.post_comment(repo, issue_number, comment)
url = f"{GITEA_URL}/api/v1/repos/{repo}/issues/{issue_number}"
req = urllib.request.Request(
url,
data=json.dumps({"state": "closed"}).encode(),
headers={
'Content-Type': 'application/json',
'Authorization': f'token {self.token}'
},
method='PATCH'
)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())
def create_workflow_issue(workflow_type, project_name, issue_number=None):
"""Create Gitea issue for workflow tracking - MANDATORY FIRST STEP"""
if issue_number:
return issue_number
client = GiteaClient()
title = f"[{workflow_type}] {project_name}"
body = f"""## {workflow_type.title()} Workflow
**Project**: {project_name}
## Workflow Progress
| Step | Status | Agent | Duration |
|------|--------|-------|----------|
| 0. Issue Creation | ✅ | - | - |
| 1. Requirements | ⏳ | @requirement-refiner | - |
| 2. Architecture | ⏳ | @system-analyst | - |
| 3. Backend | ⏳ | @backend-developer | - |
| 4. Frontend | ⏳ | @frontend-developer | - |
| 5. Testing | ⏳ | @sdet-engineer | - |
| 6. Review | ⏳ | @code-skeptic | - |
| 7. Security | ⏳ | @security-auditor | - |
| 8. Docker | ⏳ | @release-manager | - |
| 9. Documentation | ⏳ | @system-analyst | - |
| 10. Delivery | ⏳ | @evaluator | - |
## Quality Gates
| Gate | Status | Score |
|------|--------|-------|
| Requirements | ⏳ Pending | - |
| Architecture | ⏳ Pending | - |
| Implementation | ⏳ Pending | - |
| Testing | ⏳ Pending | - |
| Security | ⏳ Pending | - |
| Docker | ⏳ Pending | - |
| Documentation | ⏳ Pending | - |
| Delivery | ⏳ Pending | - |
## Checklist
- [ ] Requirements gathered
- [ ] Architecture designed
- [ ] Backend implemented
- [ ] Frontend implemented
- [ ] Tests passing
- [ ] Code reviewed
- [ ] Security audited
- [ ] Docker ready
- [ ] Documentation complete
- [ ] Final delivery validated
## Labels
- workflow
- {workflow_type}
- status: new
"""
issue = client.create_issue(
repo="UniqueSoft/APAW",
title=title,
body=body,
labels=["workflow", workflow_type, "status: new"]
)
return issue['number']
```
## Comment Templates
### Step Start
```python
def comment_start(issue_number, step_name, step_number, agent, files=None):
"""Post step start comment"""
body = f"""## 🔄 {step_name} Started
**Agent**: {agent}
**Step**: {step_number}/10
**Time**: {timestamp()}
"""
if files:
body += f"\n**Files**:\n"
for f in files:
body += f"- `{f}`\n"
body += "\n---\n*Progress comment will be updated upon completion.*"
client = GiteaClient()
client.post_comment("UniqueSoft/APAW", issue_number, body)
```
### Step Success
```python
def comment_success(issue_number, step_name, step_number, result):
"""Post step completion comment"""
body = f"""## ✅ {step_name} Complete
**Duration**: {result['duration']}
**Files Changed**: {result['files_count']}
### Artifacts Created:
"""
for artifact in result['artifacts']:
body += f"- `{artifact}`\n"
body += f"""
### Tests:
- Unit: {result['tests']['unit_passed']}/{result['tests']['unit_total']} passed
- E2E: {result['tests']['e2e_passed']}/{result['tests']['e2e_total']} passed
- Coverage: {result['tests']['coverage']}%
### Gate: {step_name}
| Check | Status |
|-------|--------|
"""
for check, passed in result['checks'].items():
status = "" if passed else ""
body += f"| {check} | {status} |\n"
body += f"""
**Next Step**: {result['next_step']}
**Progress**: {step_number * 10}%
"""
client = GiteaClient()
client.post_comment("UniqueSoft/APAW", issue_number, body)
# Update labels
client.add_label("UniqueSoft/APAW", issue_number, f"step: {step_number}")
```
### Step Error
```python
def comment_error(issue_number, step_name, step_number, error):
"""Post step error comment - BLOCKS workflow"""
body = f"""## ❌ {step_name} Failed
**Error**: {error['message']}
**Type**: {error['type']}
**File**: {error.get('file', 'N/A')}
**Time**: {timestamp()}
### Stack Trace:
```
{error.get('stack_trace', 'N/A')}
```
### Blocker:
{error['blocker']}
### How to Fix:
"""
for i, step in enumerate(error['fix_steps'], 1):
body += f"{i}. {step}\n"
body += f"""
### Cannot Proceed Until:
"""
for req in error['requirements']:
body += f"- [ ] {req}\n"
body += f"""
**Workflow PAUSED** - waiting for resolution.
Reply with "retry" to re-run this step after fixing.
"""
client = GiteaClient()
client.post_comment("UniqueSoft/APAW", issue_number, body)
client.add_label("UniqueSoft/APAW", issue_number, "status: blocked")
```
### Final Delivery
```python
def comment_delivery(issue_number, project_name, workflow_type, checks):
"""Post final delivery comment"""
body = f"""## 🎉 Workflow Complete - READY FOR CLIENT DELIVERY
**Project**: {project_name}
**Type**: {workflow_type}
**Issue**: #{issue_number}
**Total Duration**: {checks['total_duration']}
**Steps Completed**: 10/10
---
## 📦 Delivery Package
### Source Code
- **Repository**: UniqueSoft/APAW
- **Branch**: main
- **Commit**: `{checks['commit_hash']}`
### Docker
- **Image**: `{project_name}:latest`
- **Size**: {checks['docker_size']}MB
- **Health**: ✅ Passing
### Quality Score: {checks['score']}/100
---
## ✅ All Quality Gates Passed
| Gate | Status | Score |
|------|--------|-------|
| Requirements | ✅ | {checks['gates']['requirements']}/10 |
| Architecture | ✅ | {checks['gates']['architecture']}/10 |
| Implementation | ✅ | {checks['gates']['implementation']}/10 |
| Testing | ✅ | {checks['gates']['testing']}/10 |
| Security | ✅ | {checks['gates']['security']}/10 |
| Docker | ✅ | {checks['gates']['docker']}/10 |
| Documentation | ✅ | {checks['gates']['documentation']}/10 |
| Delivery | ✅ | {checks['gates']['delivery']}/10 |
| **Total** | ✅ | **{checks['total_score']}/80** |
---
## 🚀 Quick Start
```bash
# Clone and run
git clone https://git.softuniq.eu/UniqueSoft/APAW.git
cd {project_name}
docker-compose up -d
# Access
# Frontend: http://localhost
# Admin: http://localhost/admin
# API: http://localhost/api
```
---
## 📋 Client Handoff Checklist
- [x] Source code in repository
- [x] Docker builds successfully
- [x] All tests passing
- [x] Documentation complete
- [x] Security audit passed
- [x] Client can deploy independently
- [x] Demo recorded
---
**Status**: 🟢 READY FOR CLIENT DELIVERY
**Completed**: {timestamp()}
"""
client = GiteaClient()
client.post_comment("UniqueSoft/APAW", issue_number, body)
client.close_issue("UniqueSoft/APAW", issue_number, "Workflow completed successfully")
```
## Progress Tracking
```python
def update_progress_table(issue_number, step_number, step_name, status):
"""Update progress table in issue body"""
# Get current issue
client = GiteaClient()
issue = client.get_issue("UniqueSoft/APAW", issue_number)
# Parse and update progress table
lines = issue['body'].split('\n')
in_progress = False
new_lines = []
for line in lines:
if '| Step | Status |' in line:
in_progress = True
if in_progress and line.startswith(f'| {step_number}.'):
parts = line.split('|')
parts[2] = f' {status} '
parts[3] = f' @{step_name.split()[0].lower()} '
line = '|'.join(parts)
new_lines.append(line)
# Update issue
client.update_issue("UniqueSoft/APAW", issue_number, '\n'.join(new_lines))
```
## Quality Gate Validation
```python
class QualityGate:
def __init__(self, gate_name, checks):
self.gate_name = gate_name
self.checks = checks
def validate(self):
"""Validate all checks pass"""
results = {}
for check_name, check_fn in self.checks.items():
try:
results[check_name] = check_fn()
except Exception as e:
results[check_name] = False
all_passed = all(results.values())
if not all_passed:
failed = [k for k, v in results.items() if not v]
raise QualityGateError(f"Gate '{self.gate_name}' failed: {failed}")
return results
def score(self, results):
"""Calculate gate score"""
passed = sum(1 for v in results.values() if v)
total = len(results)
return round((passed / total) * 10)
# Define gates for each workflow step
GATES = {
'requirements': QualityGate('requirements', {
'User stories defined': lambda: os.path.exists('.workflow/user-stories.md'),
'Acceptance criteria': lambda: count_criteria() > 0,
'Technical constraints': lambda: os.path.exists('.workflow/requirements.md'),
'Stakeholders identified': lambda: check_stakeholders(),
}),
'architecture': QualityGate('architecture', {
'Database schema': lambda: os.path.exists('.workflow/database-schema.sql'),
'API documented': lambda: os.path.exists('.workflow/api-endpoints.md'),
'Tech stack decided': lambda: os.path.exists('.workflow/tech-stack.md'),
'Project structure': lambda: os.path.exists('backend/') and os.path.exists('frontend/'),
}),
'backend': QualityGate('backend', {
'Code exists': lambda: os.path.exists('backend/src/app.js'),
'Builds successfully': lambda: run('npm run build --prefix backend') == 0,
'No TypeScript errors': lambda: run('npm run type-check --prefix backend') == 0,
'Database connected': lambda: check_db_connection(),
}),
'frontend': QualityGate('frontend', {
'Pages created': lambda: count_files('frontend/src/views') > 0,
'Components created': lambda: count_files('frontend/src/components') > 0,
'Builds successfully': lambda: run('npm run build --prefix frontend') == 0,
'No errors': lambda: run('npm run lint --prefix frontend') == 0,
}),
'testing': QualityGate('testing', {
'Unit tests pass': lambda: run('npm test') == 0,
'E2E tests pass': lambda: run('npm run e2e') == 0,
'Coverage > 80%': lambda: get_coverage() >= 80,
'No critical bugs': lambda: count_critical_bugs() == 0,
}),
'security': QualityGate('security', {
'No vulnerabilities': lambda: run('npm audit') == 0,
'No secrets in code': lambda: scan_for_secrets() == 0,
'Auth working': lambda: test_auth() == True,
'Input validation': lambda: check_input_validation(),
}),
'docker': QualityGate('docker', {
'Image builds': lambda: run('docker-compose build') == 0,
'Container starts': lambda: run('docker-compose up -d') == 0,
'Health check': lambda: check_health() == True,
'Port accessible': lambda: check_port(8080),
}),
'documentation': QualityGate('documentation', {
'README exists': lambda: os.path.exists('README.md'),
'API docs exist': lambda: os.path.exists('docs/API.md'),
'Deployment guide': lambda: os.path.exists('docs/DEPLOYMENT.md'),
'Admin guide': lambda: os.path.exists('docs/ADMIN.md'),
}),
'delivery': QualityGate('delivery', {
'All gates passed': lambda: all(g.validate() for g in GATES.values()),
'Source in repo': lambda: run('git status --porcelain') == '',
'Demo recorded': lambda: os.path.exists('.workflow/demo.md'),
'Client can deploy': lambda: validate_deployment_instructions(),
}),
}
```
## Workflow Execution Pattern
```python
def run_workflow(workflow_type, project_name, issue_number=None):
"""Execute workflow with Gitea tracking - CLOSED LOOP"""
# Step 0: Create Issue (MANDATORY)
issue_number = create_workflow_issue(workflow_type, project_name, issue_number)
try:
# Step 1: Requirements
comment_start(issue_number, "Requirements", 1, "@requirement-refiner")
result = execute_requirements(workflow_type)
GATES['requirements'].validate()
comment_success(issue_number, "Requirements", 1, result)
# Step 2: Architecture
comment_start(issue_number, "Architecture", 2, "@system-analyst")
result = execute_architecture(workflow_type)
GATES['architecture'].validate()
comment_success(issue_number, "Architecture", 2, result)
# Step 3: Backend
comment_start(issue_number, "Backend", 3, "@backend-developer")
result = execute_backend(workflow_type)
GATES['backend'].validate()
comment_success(issue_number, "Backend", 3, result)
# Step 4: Frontend
comment_start(issue_number, "Frontend", 4, "@frontend-developer")
result = execute_frontend(workflow_type)
GATES['frontend'].validate()
comment_success(issue_number, "Frontend", 4, result)
# Step 5: Testing
comment_start(issue_number, "Testing", 5, "@sdet-engineer")
result = execute_testing(workflow_type)
GATES['testing'].validate()
comment_success(issue_number, "Testing", 5, result)
# Step 6: Review
comment_start(issue_number, "Review", 6, "@code-skeptic")
result = execute_review(workflow_type)
comment_success(issue_number, "Review", 6, result)
# Step 7: Security
comment_start(issue_number, "Security", 7, "@security-auditor")
result = execute_security(workflow_type)
GATES['security'].validate()
comment_success(issue_number, "Security", 7, result)
# Step 8: Docker
comment_start(issue_number, "Docker", 8, "@release-manager")
result = execute_docker(workflow_type)
GATES['docker'].validate()
comment_success(issue_number, "Docker", 8, result)
# Step 9: Documentation
comment_start(issue_number, "Documentation", 9, "@system-analyst")
result = execute_documentation(workflow_type)
GATES['documentation'].validate()
comment_success(issue_number, "Documentation", 9, result)
# Step 10: Delivery
comment_start(issue_number, "Delivery", 10, "@evaluator")
result = execute_delivery(workflow_type)
GATES['delivery'].validate()
comment_delivery(issue_number, project_name, workflow_type, result)
return {'success': True, 'issue': issue_number}
except QualityGateError as e:
# BLOCK workflow - don't proceed
comment_error(issue_number, e.gate_name, e.step_number, {
'message': str(e),
'type': 'QualityGateError',
'blocker': f"Quality gate '{e.gate_name}' failed",
'fix_steps': ['Review failed checks', 'Fix issues', 'Retry step'],
'requirements': ['All quality checks must pass']
})
raise
except Exception as e:
# BLOCK workflow - don't proceed
comment_error(issue_number, "Unknown", 0, {
'message': str(e),
'type': type(e).__name__,
'blocker': str(e),
'fix_steps': ['Review error', 'Fix issue', 'Retry workflow'],
'requirements': ['Error must be resolved']
})
raise
```
## Usage in Workflows
Every workflow MUST follow this pattern:
```markdown
## Step 0: Issue Creation (MANDATORY)
**Before any work starts:**
```python
issue_number = create_workflow_issue(workflow_type, project_name)
```
## Each Step MUST:
1. Post START comment to Gitea
2. Execute step logic
3. Validate quality gate
4. Post SUCCESS/ERROR comment
5. Update progress table
## Error Handling MUST:
1. Post ERROR comment to Gitea
2. Block workflow (raise exception)
3. NOT proceed to next step
4. Wait for fix and retry
```