chore: remove docker-compose (use k8s + CI/CD only)
This commit is contained in:
@@ -1,34 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
REGISTRY="forgejo.riotpiao.com/rock"
|
|
||||||
TAG="${1:-latest}"
|
|
||||||
|
|
||||||
echo "🔨 Building Poimen Application Images"
|
|
||||||
echo " Registry: $REGISTRY"
|
|
||||||
echo " Tag: $TAG"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Build memory service
|
|
||||||
echo "📦 Building poimen-memory..."
|
|
||||||
docker build -t $REGISTRY/poimen-memory:$TAG ./memory
|
|
||||||
docker push $REGISTRY/poimen-memory:$TAG
|
|
||||||
echo "✓ Pushed poimen-memory:$TAG"
|
|
||||||
|
|
||||||
# Build workflows service
|
|
||||||
echo "📦 Building poimen-workflows..."
|
|
||||||
docker build -t $REGISTRY/poimen-workflows:$TAG ./workflows
|
|
||||||
docker push $REGISTRY/poimen-workflows:$TAG
|
|
||||||
echo "✓ Pushed poimen-workflows:$TAG"
|
|
||||||
|
|
||||||
# Build frontend service
|
|
||||||
echo "📦 Building poimen-frontend..."
|
|
||||||
docker build -t $REGISTRY/poimen-frontend:$TAG ./poimen-frontend
|
|
||||||
docker push $REGISTRY/poimen-frontend:$TAG
|
|
||||||
echo "✓ Pushed poimen-frontend:$TAG"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "✅ All images built and pushed"
|
|
||||||
echo ""
|
|
||||||
echo "To deploy:"
|
|
||||||
echo " cd k8s && ./deploy.sh -a"
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: poimen
|
|
||||||
POSTGRES_PASSWORD: poimen
|
|
||||||
POSTGRES_INITDB_ARGS: -c max_connections=200
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
volumes:
|
|
||||||
- postgres-data:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U poimen"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
temporal:
|
|
||||||
image: temporalio/auto-setup:latest
|
|
||||||
ports:
|
|
||||||
- "7233:7233"
|
|
||||||
- "8233:8233"
|
|
||||||
environment:
|
|
||||||
DB: postgresql
|
|
||||||
DB_PORT: 5432
|
|
||||||
POSTGRES_USER: poimen
|
|
||||||
POSTGRES_PASSWORD: poimen
|
|
||||||
POSTGRES_SEEDS: postgres
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "tctl", "workflow", "list"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
poimen-memory:
|
|
||||||
build:
|
|
||||||
context: ./memory
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "8000:8000"
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: postgresql://poimen:poimen@postgres:5432/poimen_memory
|
|
||||||
REDIS_URL: redis://redis:6379
|
|
||||||
JWT_SECRET: dev-secret-key
|
|
||||||
LOG_LEVEL: debug
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
volumes:
|
|
||||||
- ./memory:/app
|
|
||||||
|
|
||||||
poimen-workflows:
|
|
||||||
build:
|
|
||||||
context: ./workflows
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: postgresql://poimen:poimen@postgres:5432/poimen_workflows
|
|
||||||
TEMPORAL_HOST: temporal:7233
|
|
||||||
MEMORY_SERVICE_URL: http://poimen-memory:8000
|
|
||||||
JWT_SECRET: dev-secret-key
|
|
||||||
LOG_LEVEL: debug
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
temporal:
|
|
||||||
condition: service_healthy
|
|
||||||
poimen-memory:
|
|
||||||
condition: service_started
|
|
||||||
volumes:
|
|
||||||
- ./workflows:/app
|
|
||||||
command: /app/workflows server
|
|
||||||
|
|
||||||
poimen-workflows-worker:
|
|
||||||
build:
|
|
||||||
context: ./workflows
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
environment:
|
|
||||||
DATABASE_URL: postgresql://poimen:poimen@postgres:5432/poimen_workflows
|
|
||||||
TEMPORAL_HOST: temporal:7233
|
|
||||||
MEMORY_SERVICE_URL: http://poimen-memory:8000
|
|
||||||
JWT_SECRET: dev-secret-key
|
|
||||||
LOG_LEVEL: debug
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
temporal:
|
|
||||||
condition: service_healthy
|
|
||||||
poimen-memory:
|
|
||||||
condition: service_started
|
|
||||||
volumes:
|
|
||||||
- ./workflows:/app
|
|
||||||
command: /app/workflows worker
|
|
||||||
|
|
||||||
poimen-frontend:
|
|
||||||
build:
|
|
||||||
context: ./poimen-frontend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
environment:
|
|
||||||
NEXT_PUBLIC_WORKFLOWS_API: http://localhost:8080
|
|
||||||
NEXT_PUBLIC_MEMORY_API: http://localhost:8000
|
|
||||||
NEXT_PUBLIC_AUTH_URL: http://localhost:8000/auth
|
|
||||||
OAUTH_CLIENT_ID: dev-client-id
|
|
||||||
OAUTH_CLIENT_SECRET: dev-client-secret
|
|
||||||
NODE_ENV: development
|
|
||||||
depends_on:
|
|
||||||
- poimen-workflows
|
|
||||||
- poimen-memory
|
|
||||||
volumes:
|
|
||||||
- ./poimen-frontend:/app
|
|
||||||
- /app/node_modules
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres-data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
name: poimen-network
|
|
||||||
@@ -1,322 +0,0 @@
|
|||||||
# Canvas Reasoner: Auto-Inferring Workflow Connections
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The **CanvasReasonerActivity** uses LLM reasoning to automatically suggest connections between workflow activities when users drop new nodes onto the canvas. It analyzes input/output compatibility and detects connection problems.
|
|
||||||
|
|
||||||
## Connection Logic
|
|
||||||
|
|
||||||
### How It Works
|
|
||||||
|
|
||||||
1. **Analyze Node Schemas**
|
|
||||||
- Get each activity's input/output fields from knowledge base
|
|
||||||
- Activities are classified as:
|
|
||||||
- **Generators**: No inputs, has outputs (e.g., API call, trigger)
|
|
||||||
- **Processors**: Has inputs and outputs (e.g., analyze code, security scan)
|
|
||||||
- **Sinks/Terminals**: Has inputs, no outputs (e.g., notification, approval)
|
|
||||||
|
|
||||||
2. **LLM Reasoning**
|
|
||||||
- Pass all nodes + their schemas to reasoning model
|
|
||||||
- Ask LLM to suggest edges based on:
|
|
||||||
- Type compatibility (string→string, object→object)
|
|
||||||
- Logical execution order
|
|
||||||
- Data flow requirements
|
|
||||||
- Common workflow patterns
|
|
||||||
|
|
||||||
3. **Validate Suggestions**
|
|
||||||
- Check all suggested edges exist in node map
|
|
||||||
- Skip self-loops
|
|
||||||
- Remove duplicates
|
|
||||||
|
|
||||||
4. **Compatibility Checking**
|
|
||||||
- For each suggested edge: `source → target`
|
|
||||||
- Verify source produces outputs
|
|
||||||
- Verify target accepts inputs
|
|
||||||
- Check output/input type compatibility
|
|
||||||
- Flag incompatible connections
|
|
||||||
|
|
||||||
5. **Identify Issues**
|
|
||||||
- Collect all incompatible edges
|
|
||||||
- Identify disconnected nodes (no edges in/out)
|
|
||||||
- Generate user alerts for problems
|
|
||||||
|
|
||||||
## Connection Impossibility Detection
|
|
||||||
|
|
||||||
### Why Connections Fail
|
|
||||||
|
|
||||||
1. **Missing Outputs**
|
|
||||||
```
|
|
||||||
NotifyStatusActivity → AnalyzeCodeActivity
|
|
||||||
⚠️ NotifyStatusActivity produces no outputs
|
|
||||||
Reason: Notification is terminal activity (sink)
|
|
||||||
Solution: Add an intermediate processor that has outputs
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Missing Inputs**
|
|
||||||
```
|
|
||||||
CloneRepoActivity → ApproveWorkflowActivity
|
|
||||||
⚠️ ApproveWorkflowActivity accepts no inputs
|
|
||||||
Reason: Approval is a terminal activity (sink)
|
|
||||||
Solution: ApproveWorkflowActivity only works as final step
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Type Mismatch**
|
|
||||||
```
|
|
||||||
LLMInferenceActivity (output: string) → DeploymentPreCheckActivity (input: object)
|
|
||||||
⚠️ String output cannot satisfy object input requirement
|
|
||||||
Reason: Incompatible data types
|
|
||||||
Solution: Use LLM transformation node to convert string→object
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Semantic Incompatibility**
|
|
||||||
```
|
|
||||||
NotifyStatusActivity → CloneRepoActivity
|
|
||||||
⚠️ No logical connection between these activities
|
|
||||||
Reason: Notification cannot be input to clone operation
|
|
||||||
Solution: Ensure data flow makes semantic sense
|
|
||||||
```
|
|
||||||
|
|
||||||
### Incompatibility Data Structure
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"incompatible_edges": [
|
|
||||||
{
|
|
||||||
"source": "node-1",
|
|
||||||
"target": "node-2",
|
|
||||||
"reason": "Source activity produces no outputs",
|
|
||||||
"source_needs": "any output",
|
|
||||||
"target_needs": "path, depth",
|
|
||||||
"suggestion": "Use LLM transformation to map outputs to inputs"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"disconnected_nodes": ["node-5", "node-8"],
|
|
||||||
"user_alerts": [
|
|
||||||
"⚠️ node-1 → node-2: Source activity produces no outputs. Use LLM transformation to map outputs to inputs",
|
|
||||||
"🔌 Node 'NotifyStatus-1' has no connections. Consider adding edges or removing it."
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## User Alerts
|
|
||||||
|
|
||||||
### Alert Types
|
|
||||||
|
|
||||||
1. **Incompatibility Warnings** (⚠️)
|
|
||||||
```
|
|
||||||
⚠️ source → target: reason. suggestion.
|
|
||||||
```
|
|
||||||
- Highlighted in red on canvas
|
|
||||||
- Shows in error sidebar
|
|
||||||
- Prevents workflow execution until fixed
|
|
||||||
|
|
||||||
2. **Disconnection Warnings** (🔌)
|
|
||||||
```
|
|
||||||
🔌 Node 'label' has no connections. Consider adding edges or removing it.
|
|
||||||
```
|
|
||||||
- Highlighted in yellow
|
|
||||||
- Nodes with no input/output edges
|
|
||||||
- May be valid (first step, last step) or indicate design error
|
|
||||||
|
|
||||||
3. **Type Mismatch Info** (ℹ️)
|
|
||||||
```
|
|
||||||
ℹ️ To connect source → target, use transformer to map: {source_outputs} → {target_inputs}
|
|
||||||
```
|
|
||||||
- Suggestion to use intermediate LLM node
|
|
||||||
- Provides mapping information
|
|
||||||
|
|
||||||
## Frontend Integration
|
|
||||||
|
|
||||||
### Canvas UI Feedback
|
|
||||||
|
|
||||||
When CanvasReasonerActivity returns incompatibilities:
|
|
||||||
|
|
||||||
1. **Visual Markers**
|
|
||||||
- Incompatible suggested edges: ❌ red dashed line (don't auto-add)
|
|
||||||
- Disconnected nodes: ⚠️ yellow border
|
|
||||||
|
|
||||||
2. **Sidebar Alerts**
|
|
||||||
```
|
|
||||||
🚨 Connection Issues (3)
|
|
||||||
|
|
||||||
⚠️ CloneRepo → ApproveWorkflow
|
|
||||||
Reason: ApproveWorkflow is terminal (no outputs)
|
|
||||||
Suggestion: Place ApproveWorkflow at end of workflow
|
|
||||||
|
|
||||||
⚠️ LLMInference → DeploymentPreCheck
|
|
||||||
Reason: Type mismatch (string ≠ object)
|
|
||||||
Suggestion: Add LLM transformation node
|
|
||||||
|
|
||||||
🔌 SecurityScan-1 has no incoming edges
|
|
||||||
Suggestion: Connect CloneRepo → SecurityScan
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **User Actions**
|
|
||||||
- ✅ Accept suggestions (green edges)
|
|
||||||
- ❌ Reject incompatible edges
|
|
||||||
- 🔧 Add transformer nodes
|
|
||||||
- 🗑️ Remove disconnected nodes
|
|
||||||
|
|
||||||
### API Response Example
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"suggested_edges": [
|
|
||||||
{"source": "clone-1", "target": "analyze-1"},
|
|
||||||
{"source": "analyze-1", "target": "security-1"},
|
|
||||||
{"source": "security-1", "target": "report-1"}
|
|
||||||
],
|
|
||||||
"reasoning": "Standard code review workflow: clone → analyze → scan → report",
|
|
||||||
"confidence": 0.92,
|
|
||||||
"incompatible_edges": [
|
|
||||||
{
|
|
||||||
"source": "report-1",
|
|
||||||
"target": "approve-1",
|
|
||||||
"reason": "ReportGenerator has no outputs (terminal activity)",
|
|
||||||
"suggestion": "ApproveWorkflow can only be a final step"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"disconnected_nodes": [],
|
|
||||||
"user_alerts": [
|
|
||||||
"⚠️ report-1 → approve-1: ReportGenerator has no outputs (terminal activity). ApproveWorkflow can only be a final step"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Knowledge Base Schema
|
|
||||||
|
|
||||||
Each activity in `activity_knowledge_base.json` defines:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "CloneRepoActivity",
|
|
||||||
"inputs": {
|
|
||||||
"repo": {"type": "string", "required": true},
|
|
||||||
"branch": {"type": "string", "required": false}
|
|
||||||
},
|
|
||||||
"outputs": {
|
|
||||||
"path": {"type": "string"},
|
|
||||||
"commit": {"type": "string"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Classification Rules
|
|
||||||
|
|
||||||
- **Generator** (0 inputs): trigger, API call, schedule
|
|
||||||
- **Processor** (1+ inputs, 1+ outputs): analysis, transformation, scan
|
|
||||||
- **Sink** (1+ inputs, 0 outputs): notification, approval, archive
|
|
||||||
- **Bypass** (0 inputs, 0 outputs): rare - usually error
|
|
||||||
|
|
||||||
## Common Patterns
|
|
||||||
|
|
||||||
### ✅ Valid Chains
|
|
||||||
|
|
||||||
```
|
|
||||||
CloneRepo → Analyze → SecurityScan → Report
|
|
||||||
(generator) → (processor) → (processor) → (sink)
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Trigger → LLMInference → Decision → (Branch: Notify OR Approve)
|
|
||||||
(gen) → (processor) → (processor) → (sink)
|
|
||||||
```
|
|
||||||
|
|
||||||
### ❌ Invalid Chains
|
|
||||||
|
|
||||||
```
|
|
||||||
Notify → CloneRepo ❌
|
|
||||||
(sink) → (generator) - backward flow
|
|
||||||
|
|
||||||
CloneRepo → CloneRepo → Analyze ❌
|
|
||||||
self-loop - no benefit
|
|
||||||
|
|
||||||
Analyze → Approve → Notify ❌
|
|
||||||
Approve is terminal (sink), can't output to Notify
|
|
||||||
```
|
|
||||||
|
|
||||||
## Edge Cases
|
|
||||||
|
|
||||||
### Multiple Outputs → Single Input
|
|
||||||
```
|
|
||||||
SecurityScan → Report
|
|
||||||
SecurityScan outputs: [issues, metrics, severity]
|
|
||||||
Report inputs: [report_data]
|
|
||||||
|
|
||||||
LLM must infer: bundle all outputs into single report_data object
|
|
||||||
Confidence: 0.7 (requires transformation)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Terminal Activities
|
|
||||||
- **ApproveWorkflowActivity**: Must be last (blocks workflow)
|
|
||||||
- **NotifyStatusActivity**: Can be mid-workflow (async notify)
|
|
||||||
- **ArchiveResultsActivity**: Should be last (persistence)
|
|
||||||
|
|
||||||
### Data Transformation
|
|
||||||
When source outputs don't match target inputs:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# User can insert transformer node:
|
|
||||||
LLMInference → [LLMTransformer] → DeploymentPreCheck
|
|
||||||
|
|
||||||
# Transformer:
|
|
||||||
# - Input: LLMInference.output (string)
|
|
||||||
# - Output: DeploymentPreCheck.requirements (object)
|
|
||||||
# - Action: Call LLM to convert format
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing Incompatibility Detection
|
|
||||||
|
|
||||||
### Test Case 1: Terminal Activity as Source
|
|
||||||
```go
|
|
||||||
source := db.WorkflowNode{ID: "n1", Type: "notify-status", Label: "Notify"}
|
|
||||||
target := db.WorkflowNode{ID: "n2", Type: "clone-repo", Label: "Clone"}
|
|
||||||
|
|
||||||
warnings := CheckConnectionCompatibility(source, target)
|
|
||||||
// Should warn: NotifyStatusActivity produces no outputs
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Case 2: Type Mismatch
|
|
||||||
```go
|
|
||||||
source := db.WorkflowNode{ID: "n1", Type: "llm-inference", ...}
|
|
||||||
target := db.WorkflowNode{ID: "n2", Type: "deployment-check", ...}
|
|
||||||
|
|
||||||
warnings := CheckConnectionCompatibility(source, target)
|
|
||||||
// Should warn: string output ≠ object input
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Case 3: Disconnected Node
|
|
||||||
```go
|
|
||||||
nodes := []db.WorkflowNode{n1, n2, n3}
|
|
||||||
edges := []db.WorkflowEdge{{Source: "n1", Target: "n2"}}
|
|
||||||
|
|
||||||
disconnected := IdentifyDisconnectedNodes(nodes, edges)
|
|
||||||
// Should return ["n3"]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Future Enhancements
|
|
||||||
|
|
||||||
1. **Automatic Transformer Insertion**
|
|
||||||
- Detect incompatibilities
|
|
||||||
- Auto-suggest LLM transformer nodes
|
|
||||||
- Chain transformers if needed
|
|
||||||
|
|
||||||
2. **Confidence Scoring**
|
|
||||||
- Increase when types match perfectly
|
|
||||||
- Decrease for semantic mismatches
|
|
||||||
- Factor in activity dependencies
|
|
||||||
|
|
||||||
3. **Learning from History**
|
|
||||||
- Track successful workflows
|
|
||||||
- Remember user edits to suggestions
|
|
||||||
- Improve LLM prompts over time
|
|
||||||
|
|
||||||
4. **Multi-Path Analysis**
|
|
||||||
- Suggest multiple connection topologies
|
|
||||||
- Show cost/efficiency of each
|
|
||||||
- Rank by execution time/cost
|
|
||||||
|
|
||||||
5. **Dry-Run Validation**
|
|
||||||
- Execute suggested workflow in simulation
|
|
||||||
- Catch runtime errors early
|
|
||||||
- Show data flow through each node
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,712 +0,0 @@
|
|||||||
# Workflows + Graph RAG Integration
|
|
||||||
|
|
||||||
Align Poimen Workflows with Poimen Memory System API for versioned relations, semantic queries, and intelligent canvas reasoning.
|
|
||||||
|
|
||||||
**Key Features:**
|
|
||||||
- Versioned workflow relations following `/memory/entities/{id}/versions` pattern
|
|
||||||
- Semantic edge queries via `/workflows/{id}/query/semantic/edges`
|
|
||||||
- Relation wording as Facts (matching Memory System edges schema)
|
|
||||||
- Point-in-time canvas reconstruction via `?as_of=timestamp`
|
|
||||||
- Ranking profiles for relation importance
|
|
||||||
- Automatic Graph RAG indexing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────┐
|
|
||||||
│ Workflow Canvas (React Flow) │
|
|
||||||
│ - Nodes (activities) │
|
|
||||||
│ - Edges (connections) │
|
|
||||||
└──────────────┬──────────────────┘
|
|
||||||
│ PUT /workflows/{id}
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────┐
|
|
||||||
│ CanvasReasonerActivity │
|
|
||||||
│ - Suggest edges │
|
|
||||||
│ - Validate compatibility │
|
|
||||||
│ - Generate change reasoning │
|
|
||||||
└──────────────┬──────────────────┘
|
|
||||||
│ suggested_edges + reasoning
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────┐
|
|
||||||
│ Workflows API Server │
|
|
||||||
│ - Update canvas in DB │
|
|
||||||
│ - Create version entry │
|
|
||||||
│ - Store change metadata │
|
|
||||||
└──────────────┬──────────────────┘
|
|
||||||
│ canvas_version, relations
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────┐
|
|
||||||
│ Graph RAG Backend │
|
|
||||||
│ - Store versioned relations │
|
|
||||||
│ - Index relation wording │
|
|
||||||
│ - Enable semantic queries │
|
|
||||||
└─────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Data Model
|
|
||||||
|
|
||||||
### Workflow Canvas Version
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- In memory.workflows_versions (new table)
|
|
||||||
CREATE TABLE workflow_versions (
|
|
||||||
id UUID PRIMARY KEY,
|
|
||||||
workflow_id UUID NOT NULL REFERENCES workflows(id),
|
|
||||||
customer_id UUID NOT NULL,
|
|
||||||
version INT NOT NULL,
|
|
||||||
canvas JSONB NOT NULL, -- {nodes, edges}
|
|
||||||
changed_by UUID,
|
|
||||||
change_reason TEXT,
|
|
||||||
change_type VARCHAR(50), -- 'manual', 'auto_reasoned', 'import'
|
|
||||||
reasoner_confidence FLOAT,
|
|
||||||
reasoning_metadata JSONB, -- LLM reasoning output
|
|
||||||
created_at TIMESTAMP DEFAULT NOW(),
|
|
||||||
|
|
||||||
UNIQUE(workflow_id, version),
|
|
||||||
FOREIGN KEY(workflow_id, customer_id)
|
|
||||||
REFERENCES workflows(id, customer_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- In memory.workflow_relations (replaces simple edges)
|
|
||||||
CREATE TABLE workflow_relations (
|
|
||||||
id UUID PRIMARY KEY,
|
|
||||||
workflow_id UUID NOT NULL,
|
|
||||||
version INT NOT NULL,
|
|
||||||
source_node_id VARCHAR(255),
|
|
||||||
target_node_id VARCHAR(255),
|
|
||||||
relation_type VARCHAR(100), -- 'data-flow', 'dependency', 'conditional', 'parallel'
|
|
||||||
relation_label TEXT, -- Human-readable: "SecurityScan outputs issues → Report inputs requirements"
|
|
||||||
relation_wording JSONB, -- {verb, object, context}
|
|
||||||
metadata JSONB, -- {source_output_type, target_input_type, compatibility_score}
|
|
||||||
created_at TIMESTAMP,
|
|
||||||
|
|
||||||
FOREIGN KEY(workflow_id, version)
|
|
||||||
REFERENCES workflow_versions(id, version),
|
|
||||||
INDEX (workflow_id, version)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- In memory.relation_changes (for Graph RAG indexing)
|
|
||||||
CREATE TABLE relation_changes (
|
|
||||||
id UUID PRIMARY KEY,
|
|
||||||
workflow_id UUID,
|
|
||||||
version_from INT,
|
|
||||||
version_to INT,
|
|
||||||
change_type VARCHAR(50), -- 'added', 'removed', 'modified'
|
|
||||||
relation_id UUID REFERENCES workflow_relations(id),
|
|
||||||
source_node_id VARCHAR(255),
|
|
||||||
target_node_id VARCHAR(255),
|
|
||||||
old_wording JSONB,
|
|
||||||
new_wording JSONB,
|
|
||||||
change_reason TEXT,
|
|
||||||
change_timestamp TIMESTAMP,
|
|
||||||
reasoner_confidence FLOAT,
|
|
||||||
|
|
||||||
INDEX (workflow_id, version_to)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Relation Wording Schema
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "edge-1",
|
|
||||||
"source": "clone-repo-1",
|
|
||||||
"target": "analyze-code-1",
|
|
||||||
"relation_type": "data-flow",
|
|
||||||
|
|
||||||
"relation_label": "CloneRepo outputs path → AnalyzeCode requires path",
|
|
||||||
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "outputs",
|
|
||||||
"source_output": "path (string): Local filesystem path where repo was cloned",
|
|
||||||
"target_input": "path (string, required): Local filesystem path to analyze",
|
|
||||||
"connection_type": "direct-map",
|
|
||||||
"confidence": 0.98,
|
|
||||||
"notes": "Perfect type match between CloneRepo.path and AnalyzeCode.path"
|
|
||||||
},
|
|
||||||
|
|
||||||
"metadata": {
|
|
||||||
"source_activity": "CloneRepoActivity",
|
|
||||||
"target_activity": "AnalyzeCodeActivity",
|
|
||||||
"output_type": "string",
|
|
||||||
"input_type": "string",
|
|
||||||
"compatibility_score": 0.98,
|
|
||||||
"requires_transformation": false,
|
|
||||||
"semantic_match": "File path passes directly"
|
|
||||||
},
|
|
||||||
|
|
||||||
"change_history": [
|
|
||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"action": "added",
|
|
||||||
"reason": "LLM reasoner suggested data-flow connection",
|
|
||||||
"confidence": 0.98,
|
|
||||||
"timestamp": "2025-09-05T10:00:00Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Unified API Endpoints
|
|
||||||
|
|
||||||
All workflow queries follow the unified endpoint pattern from Memory System.
|
|
||||||
|
|
||||||
### 1. Unified Workflow Query
|
|
||||||
|
|
||||||
**Endpoint:** `POST /workflows/{id}/query`
|
|
||||||
|
|
||||||
This is the primary endpoint for all workflow canvas queries (replaces separate search endpoints).
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"query": "how does code analysis flow into security scanning",
|
|
||||||
"search_type": "edges|entities|all",
|
|
||||||
"version": 3,
|
|
||||||
"relation_type": "data-flow",
|
|
||||||
"confidence_floor": 0.7,
|
|
||||||
"top_k": 10,
|
|
||||||
"find_paths": true,
|
|
||||||
"target_node_id": "security-scan-1",
|
|
||||||
"max_path_depth": 3,
|
|
||||||
"ranking_profile": "default",
|
|
||||||
"include_reasoning": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response (200 OK):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"workflow_id": "workflow-1",
|
|
||||||
"query": "how does code analysis flow into security scanning",
|
|
||||||
"search_type": "edges",
|
|
||||||
"version": 3,
|
|
||||||
"execution_time_ms": 145,
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"id": "edge_analyze_scan",
|
|
||||||
"source_node_id": "analyze-code-1",
|
|
||||||
"source_name": "AnalyzeCodeActivity",
|
|
||||||
"target_node_id": "security-scan-1",
|
|
||||||
"target_name": "SecurityScanActivity",
|
|
||||||
"relation_type": "data-flow",
|
|
||||||
"relation_label": "AnalyzeCode outputs metrics → SecurityScan requires code structure",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "provides-input-for",
|
|
||||||
"source_output": "metrics (object): Code quality and structural metrics",
|
|
||||||
"target_input": "path (string): Directory to scan",
|
|
||||||
"connection_type": "requires-transformer",
|
|
||||||
"confidence": 0.85,
|
|
||||||
"semantic_match": "Analysis metrics can guide security scan prioritization"
|
|
||||||
},
|
|
||||||
"similarity_score": 0.92,
|
|
||||||
"confidence": 0.85,
|
|
||||||
"created_at": "2025-09-05T10:00:00Z",
|
|
||||||
"metadata": {
|
|
||||||
"source": "canvas://workflow-1:v3",
|
|
||||||
"tags": ["code-review", "security"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"paths": [
|
|
||||||
{
|
|
||||||
"source_id": "analyze-code-1",
|
|
||||||
"target_id": "security-scan-1",
|
|
||||||
"path_count": 1,
|
|
||||||
"shortest_distance": 1,
|
|
||||||
"paths_found": [
|
|
||||||
{
|
|
||||||
"node_ids": ["analyze-code-1", "security-scan-1"],
|
|
||||||
"relation_types": ["data-flow"],
|
|
||||||
"distance": 1,
|
|
||||||
"total_confidence": 0.85
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"total_count": 1,
|
|
||||||
"has_more": false,
|
|
||||||
"ranking_profile": "default"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. Update Workflow Canvas (with Versioning)
|
|
||||||
|
|
||||||
**Endpoint:** `PUT /workflows/{id}`
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"nodes": [...],
|
|
||||||
"edges": [...],
|
|
||||||
"auto_reason": true,
|
|
||||||
"change_reason": "User connected CloneRepo to AnalyzeCode",
|
|
||||||
"user_id": "uuid"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "workflow-1",
|
|
||||||
"version": 3,
|
|
||||||
"canvas": {
|
|
||||||
"nodes": [...],
|
|
||||||
"edges": [...]
|
|
||||||
},
|
|
||||||
"version_info": {
|
|
||||||
"version_number": 3,
|
|
||||||
"created_at": "2025-09-05T10:05:00Z",
|
|
||||||
"created_by": "user-uuid",
|
|
||||||
"change_reason": "User connected CloneRepo to AnalyzeCode",
|
|
||||||
"change_type": "manual"
|
|
||||||
},
|
|
||||||
"relation_updates": {
|
|
||||||
"added": [
|
|
||||||
{
|
|
||||||
"source": "clone-repo-1",
|
|
||||||
"target": "analyze-code-1",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "outputs",
|
|
||||||
"source_output": "path: Local filesystem path where repo was cloned",
|
|
||||||
"target_input": "path (required): Local filesystem path to analyze",
|
|
||||||
"confidence": 0.98
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"removed": [],
|
|
||||||
"modified": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. Get Relation Version History (Memory System Pattern)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /workflows/{id}/relations/{edge_id}/versions`
|
|
||||||
|
|
||||||
Follows `/memory/entities/{id}/versions` pattern from Memory System.
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"edge_id": "edge_1",
|
|
||||||
"workflow_id": "workflow-1",
|
|
||||||
"source": "clone-repo-1",
|
|
||||||
"target": "analyze-code-1",
|
|
||||||
"versions": [
|
|
||||||
{
|
|
||||||
"version_num": 1,
|
|
||||||
"operation": "CREATE",
|
|
||||||
"snapshot": {
|
|
||||||
"relation_type": "data-flow",
|
|
||||||
"relation_label": "CloneRepo → AnalyzeCode",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "connects-to",
|
|
||||||
"confidence": 0.75
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"changed_at": "2025-09-04T12:00:00Z",
|
|
||||||
"changed_by": "system",
|
|
||||||
"fields_changed": ["relation_type", "relation_wording"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version_num": 2,
|
|
||||||
"operation": "UPDATE",
|
|
||||||
"snapshot": {
|
|
||||||
"relation_type": "data-flow",
|
|
||||||
"relation_label": "CloneRepo outputs path → AnalyzeCode requires path",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "outputs",
|
|
||||||
"source_output": "path (string)",
|
|
||||||
"target_input": "path (string, required)",
|
|
||||||
"confidence": 0.98
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"changed_at": "2025-09-05T10:00:00Z",
|
|
||||||
"changed_by": "reasoner-activity",
|
|
||||||
"fields_changed": ["relation_wording", "relation_label"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"total_versions": 2,
|
|
||||||
"current_version": 2
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. Edge Diff (Versioning Pattern)
|
|
||||||
|
|
||||||
**Endpoint:** `POST /workflows/{id}/relations/diff`
|
|
||||||
|
|
||||||
Follows `/memory/entities/diff` pattern.
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"edge_id": "edge_1",
|
|
||||||
"from_version": 1,
|
|
||||||
"to_version": 2
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"edge_id": "edge_1",
|
|
||||||
"from_version": 1,
|
|
||||||
"to_version": 2,
|
|
||||||
"source": "clone-repo-1",
|
|
||||||
"target": "analyze-code-1",
|
|
||||||
"diff": {
|
|
||||||
"added_fields": {},
|
|
||||||
"removed_fields": {},
|
|
||||||
"modified_fields": {
|
|
||||||
"relation_wording": {
|
|
||||||
"old": {
|
|
||||||
"verb": "connects-to",
|
|
||||||
"confidence": 0.75
|
|
||||||
},
|
|
||||||
"new": {
|
|
||||||
"verb": "outputs",
|
|
||||||
"source_output": "path (string)",
|
|
||||||
"target_input": "path (string, required)",
|
|
||||||
"confidence": 0.98
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"change_timeline": [
|
|
||||||
{
|
|
||||||
"version": 1,
|
|
||||||
"confidence": 0.75,
|
|
||||||
"changed_at": "2025-09-04T12:00:00Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"confidence": 0.98,
|
|
||||||
"changed_at": "2025-09-05T10:00:00Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"editors_involved": ["system", "reasoner-activity"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. Point-in-Time Canvas (Versioning Pattern)
|
|
||||||
|
|
||||||
**Endpoint:** `GET /workflows/{id}?at_version={v}` or `?as_of=2025-09-05T10:00:00Z`
|
|
||||||
|
|
||||||
Follows `/memory/entities/at` pattern.
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"workflow_id": "workflow-1",
|
|
||||||
"version": 2,
|
|
||||||
"as_of_timestamp": "2025-09-05T10:00:00Z",
|
|
||||||
"canvas": {
|
|
||||||
"nodes": [...],
|
|
||||||
"edges": [...]
|
|
||||||
},
|
|
||||||
"relations": [
|
|
||||||
{
|
|
||||||
"id": "edge_1",
|
|
||||||
"source": "clone-repo-1",
|
|
||||||
"target": "analyze-code-1",
|
|
||||||
"relation_type": "data-flow",
|
|
||||||
"relation_label": "CloneRepo outputs path → AnalyzeCode requires path",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "outputs",
|
|
||||||
"source_output": "path (string)",
|
|
||||||
"target_input": "path (string, required)",
|
|
||||||
"confidence": 0.98
|
|
||||||
},
|
|
||||||
"version": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"version_number": 2,
|
|
||||||
"created_at": "2025-09-05T10:00:00Z",
|
|
||||||
"changed_by": "reasoner-activity",
|
|
||||||
"change_reason": "LLM reasoner refined relation wording"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. Bulk Import Canvas (with Relations)
|
|
||||||
|
|
||||||
**Endpoint:** `POST /workflows/{id}/import`
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"canvas": {
|
|
||||||
"nodes": [...],
|
|
||||||
"edges": [...]
|
|
||||||
},
|
|
||||||
"relations": [
|
|
||||||
{
|
|
||||||
"source": "n1",
|
|
||||||
"target": "n2",
|
|
||||||
"relation_type": "data-flow",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "outputs",
|
|
||||||
"source_output": "result (string)",
|
|
||||||
"target_input": "input (string, required)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"change_reason": "Imported from external workflow system"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"workflow_id": "workflow-1",
|
|
||||||
"version": 4,
|
|
||||||
"canvas": {...},
|
|
||||||
"relations": {...},
|
|
||||||
"import_metadata": {
|
|
||||||
"imported_nodes": 5,
|
|
||||||
"imported_edges": 4,
|
|
||||||
"validation_status": "success",
|
|
||||||
"indexing_status": "queued_for_graph_rag"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Integration with CanvasReasonerActivity
|
|
||||||
|
|
||||||
### Flow
|
|
||||||
|
|
||||||
```
|
|
||||||
User edits canvas
|
|
||||||
↓
|
|
||||||
PUT /workflows/{id} with auto_reason=true
|
|
||||||
↓
|
|
||||||
Backend calls CanvasReasonerActivity
|
|
||||||
↓
|
|
||||||
LLM suggests edges + reasoning
|
|
||||||
↓
|
|
||||||
Generate relation_wording from suggestions
|
|
||||||
↓
|
|
||||||
Create workflow_version entry
|
|
||||||
↓
|
|
||||||
Create workflow_relations entries
|
|
||||||
↓
|
|
||||||
Index relations in Graph RAG
|
|
||||||
↓
|
|
||||||
Response includes suggested_edges + relation_wording
|
|
||||||
```
|
|
||||||
|
|
||||||
### Response Structure
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"suggested_edges": [
|
|
||||||
{
|
|
||||||
"source": "clone-1",
|
|
||||||
"target": "analyze-1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"reasoning": "Standard code review workflow",
|
|
||||||
"confidence": 0.92,
|
|
||||||
"relation_wordings": [
|
|
||||||
{
|
|
||||||
"source": "clone-1",
|
|
||||||
"target": "analyze-1",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "outputs",
|
|
||||||
"source_output": "path (string): Cloned repository path",
|
|
||||||
"target_input": "path (string, required): Directory to analyze",
|
|
||||||
"connection_type": "direct-map",
|
|
||||||
"confidence": 0.98,
|
|
||||||
"semantic_description": "Repository path flows from clone operation to analysis"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Graph RAG Indexing
|
|
||||||
|
|
||||||
### Relations Indexed
|
|
||||||
|
|
||||||
Each workflow relation creates Graph RAG entities:
|
|
||||||
|
|
||||||
```
|
|
||||||
Node: {
|
|
||||||
id: "clone-repo-1",
|
|
||||||
type: "activity",
|
|
||||||
name: "CloneRepoActivity",
|
|
||||||
workflow_id: "workflow-1",
|
|
||||||
version: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
Node: {
|
|
||||||
id: "analyze-code-1",
|
|
||||||
type: "activity",
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
Edge: {
|
|
||||||
id: "rel-1",
|
|
||||||
source: "clone-repo-1",
|
|
||||||
target: "analyze-code-1",
|
|
||||||
type: "data-flow",
|
|
||||||
label: "outputs path",
|
|
||||||
wording: {...},
|
|
||||||
version: 3,
|
|
||||||
created_at: "2025-09-05T10:00:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Semantic Queries
|
|
||||||
|
|
||||||
Users can query like:
|
|
||||||
|
|
||||||
- *"Which activities receive data from CloneRepo?"*
|
|
||||||
- *"What's the data flow from Analyze to Report?"*
|
|
||||||
- *"Which relations were added in version 3?"*
|
|
||||||
- *"Show me all type-mismatched connections"*
|
|
||||||
- *"Find workflows with Security Scan that require approval"*
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Versioning Strategy
|
|
||||||
|
|
||||||
### Version Numbering
|
|
||||||
|
|
||||||
- Increment on every canvas change
|
|
||||||
- Track change_type: `manual`, `auto_reasoned`, `import`, `rag_query_applied`
|
|
||||||
- Store reasoner_confidence for auto changes
|
|
||||||
|
|
||||||
### Relation Wording Versions
|
|
||||||
|
|
||||||
- Each relation has independent wording history
|
|
||||||
- Confidence scores tracked per version
|
|
||||||
- Sources: user input, LLM reasoner, import, RAG query
|
|
||||||
|
|
||||||
### Changelog
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"workflow_id": "workflow-1",
|
|
||||||
"total_versions": 5,
|
|
||||||
"changes": [
|
|
||||||
{
|
|
||||||
"version": 1,
|
|
||||||
"type": "created",
|
|
||||||
"timestamp": "2025-09-04T10:00:00Z",
|
|
||||||
"user": "system",
|
|
||||||
"reason": "Workflow initialized"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"type": "auto_reasoned",
|
|
||||||
"timestamp": "2025-09-04T12:00:00Z",
|
|
||||||
"reasoner_confidence": 0.89,
|
|
||||||
"changes": {
|
|
||||||
"edges_added": 4,
|
|
||||||
"edges_modified": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"version": 3,
|
|
||||||
"type": "manual",
|
|
||||||
"timestamp": "2025-09-05T10:05:00Z",
|
|
||||||
"user": "user-uuid",
|
|
||||||
"reason": "Connected SecurityScan to Report manually"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Data Flow Example
|
|
||||||
|
|
||||||
### Scenario: User drops SecurityScan node, system suggests connection
|
|
||||||
|
|
||||||
1. **User Action:** Drops SecurityScan node onto existing workflow
|
|
||||||
2. **Frontend Call:** `PUT /workflows/{id}` with new nodes + `auto_reason=true`
|
|
||||||
3. **Backend:**
|
|
||||||
- Saves canvas to `workflow_versions` v.3
|
|
||||||
- Calls CanvasReasonerActivity
|
|
||||||
4. **LLM Reasoning:**
|
|
||||||
- Analyzes: AnalyzeCode (outputs: quality, metrics) → SecurityScan (inputs: path, depth)
|
|
||||||
- Suggests: Add transformer node OR use metrics for decision
|
|
||||||
- Confidence: 0.85 (type mismatch, requires transformation)
|
|
||||||
5. **Relation Wording:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"source": "analyze-code-1",
|
|
||||||
"target": "security-scan-1",
|
|
||||||
"relation_wording": {
|
|
||||||
"verb": "provides-context-for",
|
|
||||||
"source_output": "quality (object): Code quality metrics",
|
|
||||||
"target_input": "path (string): Directory to scan",
|
|
||||||
"connection_type": "requires-transformer",
|
|
||||||
"reasoning": "Metrics inform which files to prioritize in scanning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
6. **Graph RAG:** Relations indexed automatically
|
|
||||||
7. **Response:** Frontend shows suggestions with natural language descriptions
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Implementation Checklist
|
|
||||||
|
|
||||||
- [ ] Create `workflow_versions` table in memory DB
|
|
||||||
- [ ] Create `workflow_relations` table with wording schema
|
|
||||||
- [ ] Create `relation_changes` table for tracking modifications
|
|
||||||
- [ ] Update CanvasReasonerActivity to generate relation wordings
|
|
||||||
- [ ] Implement versioned CRUD endpoints (PUT, GET, DIFF)
|
|
||||||
- [ ] Add Graph RAG indexing on relation creation
|
|
||||||
- [ ] Implement semantic query endpoint
|
|
||||||
- [ ] Add changelog view
|
|
||||||
- [ ] Test point-in-time reconstruction
|
|
||||||
- [ ] Document API in homelab-frontend/API.md
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Relation Wording Language
|
|
||||||
|
|
||||||
### Verbs (relation_type → verb mapping)
|
|
||||||
|
|
||||||
| Type | Verbs | Example |
|
|
||||||
|------|-------|---------|
|
|
||||||
| `data-flow` | outputs, inputs, receives, provides | "CloneRepo outputs path → AnalyzeCode inputs path" |
|
|
||||||
| `dependency` | must-complete-before, depends-on, requires | "SecurityScan depends-on AnalyzeCode completion" |
|
|
||||||
| `conditional` | triggers-if, branches-on, routes-to | "ApproveWorkflow branches-on result approval" |
|
|
||||||
| `parallel` | runs-alongside, concurrent-with, independent-of | "Notify runs-alongside Report generation" |
|
|
||||||
| `transformation` | transforms, converts, maps, adapts | "LLMTransform converts metrics → deployment plan" |
|
|
||||||
|
|
||||||
### Confidence Scoring
|
|
||||||
|
|
||||||
- **0.9-1.0:** Perfect match (type-compatible, direct data flow)
|
|
||||||
- **0.7-0.9:** Good match (semantic fit, minor transformation needed)
|
|
||||||
- **0.5-0.7:** Possible match (requires user confirmation)
|
|
||||||
- **<0.5:** Poor match (suggest removal or transformer)
|
|
||||||
|
|
||||||
+1
-1
@@ -9,6 +9,6 @@ metadata:
|
|||||||
app.kubernetes.io/name: poimen
|
app.kubernetes.io/name: poimen
|
||||||
app.kubernetes.io/component: orchestrator
|
app.kubernetes.io/component: orchestrator
|
||||||
data:
|
data:
|
||||||
GIT_COMMIT: "eb4c4e989" # Updated automatically by CI/CD
|
GIT_COMMIT: "84b4ca120" # Updated automatically by CI/CD
|
||||||
GIT_BRANCH: "main"
|
GIT_BRANCH: "main"
|
||||||
DEPLOYMENT_DATE: "2026-09-05"
|
DEPLOYMENT_DATE: "2026-09-05"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: poimen-worker
|
app: poimen-worker
|
||||||
annotations:
|
annotations:
|
||||||
git-commit: "eb4c4e989" # ✅ Updated on each push, triggers rolling restart
|
git-commit: "84b4ca120" # ✅ Updated on each push, triggers rolling restart
|
||||||
deployment-date: "2026-09-05"
|
deployment-date: "2026-09-05"
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
|
|||||||
Reference in New Issue
Block a user