From 4debcf00de1c59d2c27fca02e46f02fb0e18b12a Mon Sep 17 00:00:00 2001 From: christiankrag Date: Sun, 14 Dec 2025 19:21:14 +0100 Subject: [PATCH] Add AI providers, lean methodologies, and WWS skills MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add synthetic.new skill (primary AI provider) - Add z.ai skill (fallback with GLM models) - Add lean backlog management skill with WSJF prioritization - Add lean prioritization skill with scheduling/parallelization - Add WWS serverless architecture overview πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- skills/ai-providers/synthetic-new.md | 205 +++++++++++++++++ skills/ai-providers/z-ai.md | 261 +++++++++++++++++++++ skills/lean/backlog.md | 251 ++++++++++++++++++++ skills/lean/prioritization.md | 249 ++++++++++++++++++++ skills/wws/overview.md | 331 +++++++++++++++++++++++++++ 5 files changed, 1297 insertions(+) create mode 100644 skills/ai-providers/synthetic-new.md create mode 100644 skills/ai-providers/z-ai.md create mode 100644 skills/lean/backlog.md create mode 100644 skills/lean/prioritization.md create mode 100644 skills/wws/overview.md diff --git a/skills/ai-providers/synthetic-new.md b/skills/ai-providers/synthetic-new.md new file mode 100644 index 0000000..e6e9a14 --- /dev/null +++ b/skills/ai-providers/synthetic-new.md @@ -0,0 +1,205 @@ +# Skill: AI Provider - synthetic.new + +## Description +Primary AI provider for the Mylder platform. OpenAI-compatible API with access to DeepSeek, Kimi, and other high-performance models. + +## Status +**PRIMARY** - Use for all AI tasks unless fallback needed. + +## Configuration +```yaml +provider: synthetic.new +base_url: https://api.synthetic.new/openai/v1 +api_key_env: SYNTHETIC_AI_API_KEY +compatibility: openai +rate_limit: 100 requests/minute +``` + +## Available Models + +### DeepSeek-V3 (Coding & Implementation) +```json +{ + "model_id": "hf:deepseek-ai/DeepSeek-V3", + "best_for": ["code_generation", "implementation", "debugging", "refactoring"], + "context_window": 128000, + "max_output": 8192, + "temperature_range": [0.0, 2.0], + "recommended_temp": 0.3 +} +``` + +**Use when:** +- Writing production code +- Debugging issues +- Code refactoring +- API implementation +- Database queries + +### Kimi-K2-Thinking (Planning & Reasoning) +```json +{ + "model_id": "hf:moonshotai/Kimi-K2-Thinking", + "best_for": ["planning", "reasoning", "analysis", "architecture"], + "context_window": 200000, + "max_output": 4096, + "temperature_range": [0.0, 1.0], + "recommended_temp": 0.5 +} +``` + +**Use when:** +- Task planning +- Architecture decisions +- Complex reasoning +- Research synthesis +- Trade-off analysis + +## Model Selection Logic +```javascript +function selectModel(taskType, complexity) { + const modelMap = { + // Planning & Design + 'research': 'hf:moonshotai/Kimi-K2-Thinking', + 'planning': 'hf:moonshotai/Kimi-K2-Thinking', + 'architecture': 'hf:moonshotai/Kimi-K2-Thinking', + 'analysis': 'hf:moonshotai/Kimi-K2-Thinking', + + // Implementation + 'code': 'hf:deepseek-ai/DeepSeek-V3', + 'implementation': 'hf:deepseek-ai/DeepSeek-V3', + 'debugging': 'hf:deepseek-ai/DeepSeek-V3', + 'testing': 'hf:deepseek-ai/DeepSeek-V3', + 'review': 'hf:deepseek-ai/DeepSeek-V3', + + // Default + 'default': 'hf:deepseek-ai/DeepSeek-V3' + }; + + return modelMap[taskType] || modelMap.default; +} +``` + +## n8n Integration + +### HTTP Request Node Configuration +```json +{ + "method": "POST", + "url": "https://api.synthetic.new/openai/v1/chat/completions", + "headers": { + "Authorization": "Bearer {{ $env.SYNTHETIC_AI_API_KEY }}", + "Content-Type": "application/json" + }, + "body": { + "model": "hf:deepseek-ai/DeepSeek-V3", + "messages": [ + { "role": "system", "content": "{{ systemPrompt }}" }, + { "role": "user", "content": "{{ userPrompt }}" } + ], + "max_tokens": 4000, + "temperature": 0.7 + }, + "timeout": 120000 +} +``` + +### Code Node Helper +```javascript +// AI Request Helper for n8n Code Node +async function callSyntheticAI(systemPrompt, userPrompt, options = {}) { + const { + model = 'hf:deepseek-ai/DeepSeek-V3', + maxTokens = 4000, + temperature = 0.7 + } = options; + + const response = await $http.request({ + method: 'POST', + url: 'https://api.synthetic.new/openai/v1/chat/completions', + headers: { + 'Authorization': `Bearer ${$env.SYNTHETIC_AI_API_KEY}`, + 'Content-Type': 'application/json' + }, + body: { + model, + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt } + ], + max_tokens: maxTokens, + temperature + } + }); + + return response.choices[0].message.content; +} +``` + +## Error Handling + +### Retry Strategy +```javascript +const retryConfig = { + maxRetries: 3, + retryDelay: 1000, // ms + retryOn: [429, 500, 502, 503, 504], + fallbackProvider: 'z.ai' // Switch to fallback after max retries +}; +``` + +### Common Errors +| Error Code | Cause | Action | +|------------|-------|--------| +| 401 | Invalid API key | Check SYNTHETIC_AI_API_KEY | +| 429 | Rate limit | Retry with backoff or fallback to z.ai | +| 500 | Server error | Retry or fallback | +| Timeout | Long response | Increase timeout or reduce max_tokens | + +## Cost Optimization + +### Token Estimation +```javascript +// Rough estimate: 1 token β‰ˆ 4 characters +function estimateTokens(text) { + return Math.ceil(text.length / 4); +} + +// Budget check before request +function checkBudget(input, maxOutput, budgetTokens) { + const inputTokens = estimateTokens(input); + const totalEstimate = inputTokens + maxOutput; + return totalEstimate <= budgetTokens; +} +``` + +### Best Practices +1. **Use appropriate model** - Kimi for reasoning, DeepSeek for coding +2. **Set max_tokens wisely** - Don't over-allocate +3. **Cache common responses** - Use KV store for repeated queries +4. **Batch similar requests** - Group related tasks + +## Testing +```bash +# Test API connection +curl -X POST https://api.synthetic.new/openai/v1/chat/completions \ + -H "Authorization: Bearer $SYNTHETIC_AI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "hf:deepseek-ai/DeepSeek-V3", + "messages": [{"role": "user", "content": "Hello"}], + "max_tokens": 50 + }' +``` + +## Related Skills +- `ai-providers/z-ai.md` - Fallback provider +- `code/implement.md` - Code generation with AI +- `design-thinking/ideate.md` - Solution brainstorming + +## Token Budget +- Max input: 500 tokens +- Max output: 800 tokens + +## Model +- Recommended: haiku (configuration lookup) diff --git a/skills/ai-providers/z-ai.md b/skills/ai-providers/z-ai.md new file mode 100644 index 0000000..acf8402 --- /dev/null +++ b/skills/ai-providers/z-ai.md @@ -0,0 +1,261 @@ +# Skill: AI Provider - z.ai + +## Description +Fallback AI provider with GLM (General Language Model) support. Use when synthetic.new is unavailable or when GLM models are superior for specific tasks. + +## Status +**FALLBACK** - Use when: +1. synthetic.new rate limits or errors +2. GLM models outperform alternatives for the task +3. New models available earlier on z.ai + +## Configuration +```yaml +provider: z.ai +base_url: https://api.z.ai/v1 +api_key_env: Z_AI_API_KEY +compatibility: openai +rate_limit: 60 requests/minute +``` + +**Note:** API key needs to be configured. Check z.ai dashboard for key generation. + +## Available Models + +### GLM-4-Plus (Reasoning & Analysis) +```json +{ + "model_id": "glm-4-plus", + "best_for": ["reasoning", "analysis", "chinese_language", "long_context"], + "context_window": 128000, + "max_output": 4096, + "temperature_range": [0.0, 1.0], + "recommended_temp": 0.5, + "strengths": ["Chinese content", "Logical reasoning", "Long documents"] +} +``` + +**Use when:** +- Complex logical reasoning +- Chinese language content +- Long document analysis +- Comparative analysis + +### GLM-4-Flash (Fast Responses) +```json +{ + "model_id": "glm-4-flash", + "best_for": ["quick_responses", "simple_tasks", "high_volume"], + "context_window": 32000, + "max_output": 2048, + "temperature_range": [0.0, 1.0], + "recommended_temp": 0.3, + "strengths": ["Speed", "Cost efficiency", "Simple tasks"] +} +``` + +**Use when:** +- Quick classification +- Simple transformations +- High-volume processing +- Cost-sensitive operations + +### GLM-4-Long (Extended Context) +```json +{ + "model_id": "glm-4-long", + "best_for": ["long_documents", "codebase_analysis", "summarization"], + "context_window": 1000000, + "max_output": 4096, + "temperature_range": [0.0, 1.0], + "recommended_temp": 0.3, + "strengths": ["1M token context", "Document processing", "Code analysis"] +} +``` + +**Use when:** +- Entire codebase analysis +- Long document summarization +- Multi-file code review + +## Model Selection Logic +```javascript +function selectZAIModel(taskType, contextLength) { + // Context-based selection + if (contextLength > 128000) { + return 'glm-4-long'; + } + + const modelMap = { + // Fast operations + 'classification': 'glm-4-flash', + 'extraction': 'glm-4-flash', + 'simple_qa': 'glm-4-flash', + + // Complex reasoning + 'reasoning': 'glm-4-plus', + 'analysis': 'glm-4-plus', + 'planning': 'glm-4-plus', + + // Long context + 'codebase': 'glm-4-long', + 'summarization': 'glm-4-long', + + // Default + 'default': 'glm-4-plus' + }; + + return modelMap[taskType] || modelMap.default; +} +``` + +## Fallback Logic + +### When to Fallback from synthetic.new +```javascript +async function callWithFallback(systemPrompt, userPrompt, options = {}) { + const primaryResult = await callSyntheticAI(systemPrompt, userPrompt, options); + + // Check for fallback conditions + if (primaryResult.error) { + const errorCode = primaryResult.error.code; + + // Rate limit or server error - fallback to z.ai + if ([429, 500, 502, 503, 504].includes(errorCode)) { + console.log('Falling back to z.ai'); + return await callZAI(systemPrompt, userPrompt, options); + } + } + + return primaryResult; +} +``` + +### GLM Superiority Conditions +```javascript +function shouldPreferGLM(task) { + const glmSuperiorTasks = [ + 'chinese_translation', + 'chinese_content', + 'million_token_context', + 'cost_optimization', + 'new_model_testing' + ]; + + return glmSuperiorTasks.includes(task.type); +} +``` + +## n8n Integration + +### HTTP Request Node Configuration +```json +{ + "method": "POST", + "url": "https://api.z.ai/v1/chat/completions", + "headers": { + "Authorization": "Bearer {{ $env.Z_AI_API_KEY }}", + "Content-Type": "application/json" + }, + "body": { + "model": "glm-4-plus", + "messages": [ + { "role": "system", "content": "{{ systemPrompt }}" }, + { "role": "user", "content": "{{ userPrompt }}" } + ], + "max_tokens": 4000, + "temperature": 0.5 + }, + "timeout": 90000 +} +``` + +### Code Node Helper +```javascript +// z.ai Request Helper for n8n Code Node +async function callZAI(systemPrompt, userPrompt, options = {}) { + const { + model = 'glm-4-plus', + maxTokens = 4000, + temperature = 0.5 + } = options; + + const response = await $http.request({ + method: 'POST', + url: 'https://api.z.ai/v1/chat/completions', + headers: { + 'Authorization': `Bearer ${$env.Z_AI_API_KEY}`, + 'Content-Type': 'application/json' + }, + body: { + model, + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt } + ], + max_tokens: maxTokens, + temperature + } + }); + + return response.choices[0].message.content; +} +``` + +## Comparison: synthetic.new vs z.ai + +| Feature | synthetic.new | z.ai | +|---------|---------------|------| +| Primary Use | All tasks | Fallback + GLM tasks | +| Best Model (Code) | DeepSeek-V3 | GLM-4-Flash | +| Best Model (Reasoning) | Kimi-K2-Thinking | GLM-4-Plus | +| Max Context | 200K | 1M (GLM-4-Long) | +| Chinese Support | Good | Excellent | +| Rate Limit | 100/min | 60/min | +| Cost | Standard | Lower (Flash) | + +## Setup Instructions + +### 1. Get API Key +1. Visit https://z.ai/dashboard +2. Create account or login +3. Navigate to API Keys +4. Generate new key +5. Store as `Z_AI_API_KEY` environment variable + +### 2. Configure in Coolify +```bash +# Add to service environment variables +Z_AI_API_KEY=your_key_here +``` + +### 3. Test Connection +```bash +curl -X POST https://api.z.ai/v1/chat/completions \ + -H "Authorization: Bearer $Z_AI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "glm-4-flash", + "messages": [{"role": "user", "content": "Hello"}], + "max_tokens": 50 + }' +``` + +## Error Handling +| Error Code | Cause | Action | +|------------|-------|--------| +| 401 | Invalid API key | Check Z_AI_API_KEY | +| 429 | Rate limit | Wait and retry | +| 400 | Invalid model | Check model name | + +## Related Skills +- `ai-providers/synthetic-new.md` - Primary provider +- `code/implement.md` - Code generation +- `design-thinking/ideate.md` - Solution brainstorming + +## Token Budget +- Max input: 500 tokens +- Max output: 800 tokens + +## Model +- Recommended: haiku (configuration lookup) diff --git a/skills/lean/backlog.md b/skills/lean/backlog.md new file mode 100644 index 0000000..5f7e4d5 --- /dev/null +++ b/skills/lean/backlog.md @@ -0,0 +1,251 @@ +# Skill: Lean - Backlog Management + +## Description +Manage and prioritize product backlog using WSJF (Weighted Shortest Job First) and lean principles for optimal value delivery. + +## Input +- **project_id**: Project identifier (required) +- **action**: list|add|prioritize|groom|estimate (required) +- **item**: Backlog item details for add/update (optional) +- **filters**: Status, phase, assignee filters (optional) + +## Backlog Item Structure +```json +{ + "id": "BLI-042", + "title": "Add dark mode toggle", + "description": "Allow users to switch between light and dark themes", + "type": "feature|bug|tech_debt|spike", + "phase": "empathize|define|ideate|prototype|test", + "status": "idea|ready|in_progress|review|done|blocked", + "priority_score": 8.5, + "scoring": { + "user_value": 7, + "time_criticality": 3, + "risk_reduction": 2, + "effort": 3 + }, + "story_points": 5, + "assigned_agent": "frontend|backend|tester|devops|pm", + "dependencies": ["BLI-040", "BLI-041"], + "labels": ["ux", "settings", "mvp"], + "acceptance_criteria": [ + "Toggle visible in settings page", + "Theme persists across sessions", + "Respects system preference by default" + ], + "created_at": "2024-12-14T10:00:00Z", + "updated_at": "2024-12-14T15:30:00Z", + "sprint_id": null +} +``` + +## WSJF Prioritization + +### Formula +``` +Priority Score = (User Value + Time Criticality + Risk Reduction) / Effort + +Scale: 1-10 for each factor +Result: Higher score = Higher priority +``` + +### Scoring Guide + +**User Value (1-10):** +- 10: Core feature, all users need +- 7-9: Important feature, most users benefit +- 4-6: Nice to have, some users want +- 1-3: Edge case, few users affected + +**Time Criticality (1-10):** +- 10: Must ship this sprint, blocking release +- 7-9: Needed soon, customer commitment +- 4-6: Planned for quarter, flexible timing +- 1-3: Backlog, no deadline + +**Risk Reduction (1-10):** +- 10: Eliminates critical security/stability risk +- 7-9: Reduces significant technical debt +- 4-6: Improves maintainability +- 1-3: Minor improvement + +**Effort (1-10):** +- 1-2: Trivial, < 2 hours +- 3-4: Small, 2-8 hours +- 5-6: Medium, 1-2 days +- 7-8: Large, 3-5 days +- 9-10: Epic, > 1 week (should be split) + +### Priority Buckets +``` +Score > 10: πŸ”₯ Critical - Do immediately +Score 7-10: ⚑ High - Sprint commitment +Score 4-7: πŸ“Œ Medium - Plan for next sprint +Score < 4: πŸ’€ Low - Future backlog +``` + +## Backlog Actions + +### List Backlog +```json +{ + "action": "list", + "filters": { + "status": ["ready", "in_progress"], + "phase": "prototype", + "label": "mvp" + }, + "sort": "priority_score", + "limit": 20 +} +``` + +### Add Item +```json +{ + "action": "add", + "item": { + "title": "Implement password reset flow", + "description": "Users need ability to reset forgotten passwords", + "type": "feature", + "phase": "prototype", + "labels": ["auth", "mvp"], + "acceptance_criteria": [ + "Email sent with reset link", + "Link expires after 1 hour", + "Password requirements enforced" + ] + } +} +``` + +### Prioritize Backlog +```json +{ + "action": "prioritize", + "items": [ + { "id": "BLI-042", "user_value": 7, "time_criticality": 3, "risk_reduction": 2, "effort": 3 }, + { "id": "BLI-043", "user_value": 9, "time_criticality": 8, "risk_reduction": 5, "effort": 5 } + ] +} +``` + +### Groom Items +```json +{ + "action": "groom", + "item_id": "BLI-042", + "updates": { + "description": "Updated description with more detail", + "acceptance_criteria": ["New criteria"], + "story_points": 8, + "status": "ready" + } +} +``` + +## Output Format +```json +{ + "status": "success", + "action": "list", + "backlog": { + "total_items": 45, + "ready_items": 12, + "in_progress": 5, + "blocked": 1 + }, + "items": [ + { + "id": "BLI-043", + "title": "User authentication", + "priority_score": 7.33, + "status": "ready", + "story_points": 8, + "phase": "prototype" + } + ], + "recommendations": [ + { + "type": "split", + "item_id": "BLI-050", + "reason": "Effort score 9 - consider breaking into smaller items" + }, + { + "type": "prioritize", + "item_id": "BLI-043", + "reason": "High time criticality, move to top" + } + ], + "next_step": "Plan sprint with /sprint plan" +} +``` + +## AI Advisory + +### Recommendations Engine +```javascript +function generateRecommendations(backlog) { + const recommendations = []; + + // Large items should be split + backlog.filter(i => i.scoring.effort >= 8).forEach(item => { + recommendations.push({ + type: 'split', + item_id: item.id, + reason: `Effort ${item.scoring.effort} is too high. Split into 2-3 smaller items.`, + priority: 'high' + }); + }); + + // Blocked items need attention + backlog.filter(i => i.status === 'blocked').forEach(item => { + recommendations.push({ + type: 'unblock', + item_id: item.id, + reason: `Item blocked. Check dependencies: ${item.dependencies.join(', ')}`, + priority: 'critical' + }); + }); + + // Old items in "idea" status + const oldIdeas = backlog.filter(i => + i.status === 'idea' && + daysSince(i.created_at) > 30 + ); + if (oldIdeas.length > 5) { + recommendations.push({ + type: 'cleanup', + reason: `${oldIdeas.length} items in "idea" status for 30+ days. Review or remove.`, + priority: 'medium' + }); + } + + return recommendations; +} +``` + +## Quality Gates +- [ ] All items have clear titles +- [ ] Ready items have acceptance criteria +- [ ] WSJF scores calculated +- [ ] Dependencies documented +- [ ] Large items flagged for splitting +- [ ] Blocked items have resolution plan + +## Token Budget +- Max input: 800 tokens +- Max output: 1500 tokens + +## Model +- Recommended: sonnet (prioritization reasoning) + +## Philosophy +> "Build less, ship faster. Priority is about saying no." + +**Keep it simple:** +- Small items > Large epics +- Done > Perfect +- User value > Technical elegance +- Weekly grooming beats quarterly planning diff --git a/skills/lean/prioritization.md b/skills/lean/prioritization.md new file mode 100644 index 0000000..0167372 --- /dev/null +++ b/skills/lean/prioritization.md @@ -0,0 +1,249 @@ +# Skill: Lean - Prioritization + +## Description +Apply lean prioritization frameworks to make decisions about what to build next. Uses WSJF, MoSCoW, and effort/impact matrices. + +## Input +- **items**: List of items to prioritize (required) +- **framework**: wsjf|moscow|effort_impact|rice (optional, default: wsjf) +- **constraints**: Time, budget, capacity limits (optional) +- **weights**: Custom weights for scoring factors (optional) + +## Prioritization Frameworks + +### 1. WSJF (Weighted Shortest Job First) +**Best for:** Sprint planning, feature prioritization + +``` +Priority = (User Value + Time Criticality + Risk Reduction) / Job Size + +Higher score = Do first +``` + +**Scoring Matrix:** +| Factor | 1-3 | 4-6 | 7-9 | 10 | +|--------|-----|-----|-----|-----| +| User Value | Few users | Some users | Most users | All users | +| Time Criticality | No deadline | Quarter | Month | This sprint | +| Risk Reduction | Minor | Moderate | Significant | Critical | +| Job Size (effort) | < 2 hours | 1-2 days | 3-5 days | > 1 week | + +**Example:** +```json +{ + "item": "Add password reset", + "user_value": 8, + "time_criticality": 7, + "risk_reduction": 6, + "job_size": 5, + "wsjf_score": 4.2 +} +// Score = (8 + 7 + 6) / 5 = 4.2 +``` + +### 2. MoSCoW Method +**Best for:** Release planning, MVP definition + +| Category | Description | Guidance | +|----------|-------------|----------| +| **M**ust Have | Non-negotiable, core functionality | Release blocked without | +| **S**hould Have | Important but not critical | Include if time permits | +| **C**ould Have | Nice to have | Descope first if needed | +| **W**on't Have | Out of scope for this release | Document for future | + +**Distribution Rule:** +- Must: 60% of effort +- Should: 20% of effort +- Could: 20% of effort +- Won't: 0% (explicitly excluded) + +### 3. Effort/Impact Matrix +**Best for:** Quick prioritization, team discussions + +``` + High Impact + β”‚ + Quick Wins β”‚ Major Projects + (Do Now) β”‚ (Plan Carefully) +─────────────────┼───────────────────── + Fill-Ins β”‚ Thankless Tasks + (If Time) β”‚ (Avoid/Delegate) + β”‚ + Low Impact + +Low Effort ─────────────── High Effort +``` + +**Quadrant Actions:** +1. **Quick Wins** (High Impact, Low Effort): Do immediately +2. **Major Projects** (High Impact, High Effort): Schedule, break down +3. **Fill-Ins** (Low Impact, Low Effort): Do when free +4. **Thankless Tasks** (Low Impact, High Effort): Eliminate or defer + +### 4. RICE Framework +**Best for:** Product decisions with reach data + +``` +RICE Score = (Reach Γ— Impact Γ— Confidence) / Effort + +Reach: Users affected per quarter +Impact: 0.25 (minimal) to 3 (massive) +Confidence: 0-100% +Effort: Person-months +``` + +## Scheduling & Parallelization + +### Dependency Resolution +```json +{ + "item_id": "BLI-050", + "depends_on": ["BLI-048", "BLI-049"], + "blocks": ["BLI-053", "BLI-054"], + "parallel_with": ["BLI-051", "BLI-052"], + "scheduling": { + "earliest_start": "After BLI-048 & BLI-049 complete", + "can_parallelize": true, + "parallelization_candidates": ["BLI-051", "BLI-052"] + } +} +``` + +### Parallelization Rules +```javascript +function canParallelize(itemA, itemB) { + // No shared dependencies + const sharedDeps = itemA.depends_on.filter(d => + itemB.depends_on.includes(d) + ); + if (sharedDeps.length > 0) return false; + + // Different agents + if (itemA.assigned_agent === itemB.assigned_agent) return false; + + // No blocking relationship + if (itemA.blocks.includes(itemB.id)) return false; + if (itemB.blocks.includes(itemA.id)) return false; + + return true; +} +``` + +### Optimal Schedule Generation +```json +{ + "schedule": { + "week_1": { + "parallel_tracks": [ + { "agent": "frontend", "items": ["BLI-050", "BLI-051"] }, + { "agent": "backend", "items": ["BLI-048", "BLI-049"] } + ], + "capacity_used": "85%" + }, + "week_2": { + "parallel_tracks": [ + { "agent": "frontend", "items": ["BLI-053"] }, + { "agent": "backend", "items": ["BLI-052"] }, + { "agent": "tester", "items": ["BLI-050-test", "BLI-051-test"] } + ], + "capacity_used": "90%" + } + }, + "critical_path": ["BLI-048", "BLI-050", "BLI-053"], + "total_duration": "2 weeks", + "parallelization_savings": "40%" +} +``` + +## Output Format +```json +{ + "status": "success", + "framework": "wsjf", + "prioritized_items": [ + { + "rank": 1, + "id": "BLI-043", + "title": "User authentication", + "score": 7.33, + "category": "must_have", + "quadrant": "quick_win" + }, + { + "rank": 2, + "id": "BLI-050", + "title": "Password reset", + "score": 5.67, + "category": "must_have", + "quadrant": "major_project" + } + ], + "schedule": { + "sprint_1": ["BLI-043", "BLI-045"], + "sprint_2": ["BLI-050", "BLI-047"], + "backlog": ["BLI-055", "BLI-060"] + }, + "parallelization": { + "recommended_groups": [ + ["BLI-043", "BLI-044"], + ["BLI-050", "BLI-051"] + ], + "time_savings": "35%" + }, + "recommendations": [ + "BLI-050 has effort 9 - consider splitting", + "BLI-043 and BLI-044 can run in parallel", + "Remove BLI-060 - low impact, high effort" + ], + "next_step": "Commit to sprint with /sprint plan" +} +``` + +## Decision Matrix Template +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ PRIORITIZATION DECISION β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Items Evaluated: 25 β”‚ +β”‚ Framework: WSJF + Effort/Impact β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ MUST DO (Score > 6) β”‚ SHOULD DO (Score 4-6) β”‚ β”‚ +β”‚ β”‚ β€’ User auth (7.33) β”‚ β€’ Dark mode (5.20) β”‚ β”‚ +β”‚ β”‚ β€’ Password reset (6.67) β”‚ β€’ Notifications (4.80) β”‚ β”‚ +β”‚ β”‚ β€’ Profile page (6.40) β”‚ β€’ Search (4.50) β”‚ β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ +β”‚ β”‚ COULD DO (Score 2-4) β”‚ WON'T DO (Score < 2) β”‚ β”‚ +β”‚ β”‚ β€’ Export CSV (3.50) β”‚ β€’ Social login (1.80) β”‚ β”‚ +β”‚ β”‚ β€’ Keyboard shortcuts (2.90)β”‚ β€’ Mobile app (1.20) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ Recommended: Focus on MUST DO items for next 2 sprints β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Quality Gates +- [ ] All items have consistent scoring +- [ ] Dependencies documented +- [ ] Parallelization opportunities identified +- [ ] Schedule accounts for capacity +- [ ] Clear decision rationale +- [ ] Stakeholder alignment + +## Token Budget +- Max input: 1000 tokens +- Max output: 1500 tokens + +## Model +- Recommended: sonnet (decision reasoning) + +## Philosophy +> "If everything is important, nothing is." + +**Keep it simple:** +- Prioritize ruthlessly +- Say no to low-impact work +- Parallelize aggressively +- Ship the most valuable thing first diff --git a/skills/wws/overview.md b/skills/wws/overview.md new file mode 100644 index 0000000..0eb166c --- /dev/null +++ b/skills/wws/overview.md @@ -0,0 +1,331 @@ +# Skill: WWS (Serverless Functions) Overview + +## Description +Architecture and implementation guide for WWS (Web Worker Services) - serverless functions for edge computing in the Mylder platform. + +## What is WWS? +WWS is our serverless function layer that runs lightweight compute at the edge, reducing VPS load and improving response times. Similar to Cloudflare Workers but platform-agnostic. + +## Architecture +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ USER REQUEST β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ EDGE LAYER (WWS) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Auth β”‚ β”‚ Rate β”‚ β”‚ Model β”‚ β”‚ Cache β”‚ β”‚ +β”‚ β”‚ Guard β”‚ β”‚ Limiter β”‚ β”‚ Router β”‚ β”‚ Manager β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚synthetic β”‚ β”‚ z.ai β”‚ β”‚ Origin β”‚ + β”‚ .new β”‚ β”‚(fallback)β”‚ β”‚ VPS β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Core Functions + +### 1. Auth Guard +```javascript +// Edge authentication validation +export async function authGuard(request, env) { + const token = request.headers.get('Authorization')?.split('Bearer ')[1]; + + // Fast KV lookup + const session = await env.SESSIONS.get(token); + if (session) { + return { valid: true, user: JSON.parse(session), source: 'cache' }; + } + + // Fallback to Supabase + const supabaseUser = await validateWithSupabase(token, env); + if (supabaseUser) { + await env.SESSIONS.put(token, JSON.stringify(supabaseUser), { + expirationTtl: 3600 // 1 hour + }); + return { valid: true, user: supabaseUser, source: 'origin' }; + } + + return { valid: false }; +} +``` + +### 2. Rate Limiter +```javascript +// Per-user, per-endpoint rate limiting +export async function rateLimiter(request, env) { + const userId = request.headers.get('X-User-ID') || 'anonymous'; + const endpoint = new URL(request.url).pathname; + const key = `rate:${userId}:${endpoint}`; + + const current = await env.RATE_LIMITS.get(key) || '0'; + const count = parseInt(current, 10); + + const limits = { + '/api/ai/chat': 60, // 60 requests per minute + '/api/ai/generate': 20, // 20 per minute + 'default': 100 // 100 per minute + }; + + const limit = limits[endpoint] || limits.default; + + if (count >= limit) { + return { + allowed: false, + retryAfter: 60, + remaining: 0 + }; + } + + await env.RATE_LIMITS.put(key, String(count + 1), { + expirationTtl: 60 + }); + + return { + allowed: true, + remaining: limit - count - 1 + }; +} +``` + +### 3. Model Router +```javascript +// Intelligent AI model routing +export async function modelRouter(task, env) { + const { type, complexity, context_length } = task; + + // Route based on task characteristics + const routing = { + // Primary: synthetic.new + primary: { + provider: 'synthetic.new', + base_url: 'https://api.synthetic.new/openai/v1', + models: { + code: 'hf:deepseek-ai/DeepSeek-V3', + reasoning: 'hf:moonshotai/Kimi-K2-Thinking' + } + }, + // Fallback: z.ai + fallback: { + provider: 'z.ai', + base_url: 'https://api.z.ai/v1', + models: { + code: 'glm-4-flash', + reasoning: 'glm-4-plus', + long_context: 'glm-4-long' + } + } + }; + + // Special cases for z.ai + if (context_length > 128000) { + return { + ...routing.fallback, + model: routing.fallback.models.long_context, + reason: 'Context exceeds 128K, using GLM-4-Long' + }; + } + + // Default: synthetic.new + const modelType = ['code', 'implementation', 'debugging'].includes(type) + ? 'code' + : 'reasoning'; + + return { + ...routing.primary, + model: routing.primary.models[modelType], + reason: `Standard ${modelType} task` + }; +} +``` + +### 4. Cache Manager +```javascript +// Stale-while-revalidate caching +export async function cacheManager(request, env, handler) { + const cacheKey = new URL(request.url).pathname; + + // Check cache + const cached = await env.RESPONSE_CACHE.get(cacheKey, { type: 'json' }); + + if (cached) { + const age = Date.now() - cached.timestamp; + const maxAge = 60000; // 1 minute + const staleAge = 300000; // 5 minutes + + // Fresh cache + if (age < maxAge) { + return { data: cached.data, source: 'cache', age }; + } + + // Stale-while-revalidate + if (age < staleAge) { + // Return stale, revalidate in background + env.ctx.waitUntil(revalidate(cacheKey, handler, env)); + return { data: cached.data, source: 'stale', age }; + } + } + + // No cache, fetch fresh + const fresh = await handler(); + await env.RESPONSE_CACHE.put(cacheKey, JSON.stringify({ + data: fresh, + timestamp: Date.now() + })); + + return { data: fresh, source: 'origin', age: 0 }; +} + +async function revalidate(key, handler, env) { + const fresh = await handler(); + await env.RESPONSE_CACHE.put(key, JSON.stringify({ + data: fresh, + timestamp: Date.now() + })); +} +``` + +## Deployment Options + +### Option 1: Cloudflare Workers +```yaml +# wrangler.toml +name = "mylder-wws" +main = "src/index.ts" +compatibility_date = "2024-12-01" + +[[kv_namespaces]] +binding = "SESSIONS" +id = "xxx" + +[[kv_namespaces]] +binding = "RATE_LIMITS" +id = "xxx" + +[[kv_namespaces]] +binding = "RESPONSE_CACHE" +id = "xxx" +``` + +### Option 2: Deno Deploy +```typescript +// main.ts +import { serve } from "https://deno.land/std/http/server.ts"; + +serve(async (req) => { + const url = new URL(req.url); + + if (url.pathname.startsWith('/api/ai/')) { + return handleAIRequest(req); + } + + return new Response('Not Found', { status: 404 }); +}, { port: 8000 }); +``` + +### Option 3: Self-Hosted (Docker) +```dockerfile +# Dockerfile.wws +FROM denoland/deno:1.38.0 + +WORKDIR /app +COPY . . + +RUN deno cache main.ts + +EXPOSE 8000 +CMD ["deno", "run", "--allow-net", "--allow-env", "main.ts"] +``` + +## Integration Points + +### n8n Workflow Integration +```json +{ + "name": "WWS Call", + "type": "n8n-nodes-base.httpRequest", + "parameters": { + "method": "POST", + "url": "https://wws.mylder.io/api/ai/chat", + "headers": { + "Authorization": "Bearer {{ $env.WWS_API_KEY }}", + "X-Task-Type": "{{ $json.taskType }}" + }, + "body": { + "messages": "{{ $json.messages }}", + "context": "{{ $json.context }}" + } + } +} +``` + +### Frontend Integration +```typescript +// lib/wws.ts +export async function callWWS(endpoint: string, data: any) { + const response = await fetch(`${process.env.NEXT_PUBLIC_WWS_URL}${endpoint}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${getSession().token}` + }, + body: JSON.stringify(data) + }); + + const result = await response.json(); + + // Handle rate limiting + if (response.status === 429) { + const retryAfter = response.headers.get('Retry-After'); + throw new RateLimitError(retryAfter); + } + + return result; +} +``` + +## Latency Targets +| Operation | Target | Fallback | +|-----------|--------|----------| +| Auth validation | < 10ms | < 300ms (origin) | +| Rate limit check | < 5ms | N/A | +| Model routing | < 2ms | N/A | +| Cache hit | < 10ms | N/A | +| AI request (primary) | < 5s | < 10s (fallback) | + +## Cost Model +``` +Cloudflare Workers: +- Free: 100K requests/day +- Paid: $5/month + $0.50/million requests + +KV Storage: +- Free: 100K reads/day, 1K writes/day +- Paid: $0.50/million reads, $5/million writes + +Estimated (1M users/month): +- Workers: ~$5/month +- KV: ~$25/month +- Total: ~$30/month +``` + +## Related Skills +- `wws/edge-auth.md` - Detailed auth implementation +- `wws/rate-limit.md` - Rate limiting patterns +- `wws/model-router.md` - AI model selection +- `ai-providers/synthetic-new.md` - Primary AI provider +- `ai-providers/z-ai.md` - Fallback provider + +## Token Budget +- Max input: 500 tokens +- Max output: 1200 tokens + +## Model +- Recommended: sonnet (architecture understanding)