From da5c3651837618d16311b7d1f7693388f02c41b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8NW=C2=A8?= <¨neroworld@mail.ru¨> Date: Sun, 5 Apr 2026 01:40:26 +0100 Subject: [PATCH] feat: add Gitea workflow integration with quality gates and closed-loop execution --- .kilo/WORKFLOW_AUDIT.md | 279 ++++++++++++ .kilo/commands/landing-page.md | 233 ++++++++-- .kilo/skills/gitea-workflow/SKILL.md | 615 +++++++++++++++++++++++++++ 3 files changed, 1097 insertions(+), 30 deletions(-) create mode 100644 .kilo/WORKFLOW_AUDIT.md create mode 100644 .kilo/skills/gitea-workflow/SKILL.md diff --git a/.kilo/WORKFLOW_AUDIT.md b/.kilo/WORKFLOW_AUDIT.md new file mode 100644 index 0000000..596ca70 --- /dev/null +++ b/.kilo/WORKFLOW_AUDIT.md @@ -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 \ No newline at end of file diff --git a/.kilo/commands/landing-page.md b/.kilo/commands/landing-page.md index 47c3f28..1e0d8de 100644 --- a/.kilo/commands/landing-page.md +++ b/.kilo/commands/landing-page.md @@ -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 diff --git a/.kilo/skills/gitea-workflow/SKILL.md b/.kilo/skills/gitea-workflow/SKILL.md new file mode 100644 index 0000000..5bb342a --- /dev/null +++ b/.kilo/skills/gitea-workflow/SKILL.md @@ -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 +``` \ No newline at end of file