Add AI providers, lean methodologies, and WWS skills

- 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 <noreply@anthropic.com>
This commit is contained in:
2025-12-14 19:21:14 +01:00
parent 539657f83f
commit 4debcf00de
5 changed files with 1297 additions and 0 deletions

View File

@@ -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)

261
skills/ai-providers/z-ai.md Normal file
View File

@@ -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)

251
skills/lean/backlog.md Normal file
View File

@@ -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

View File

@@ -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

331
skills/wws/overview.md Normal file
View File

@@ -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)