rdev/docs/legal/patent-specification.md
jordan d69da6d627 feat: add structured logging infrastructure and SDLC extensions
Major changes:
- Add internal/logging package with field constants, context propagation,
  sensitive data auto-redaction, and per-component log levels
- Add worker timeout constants (TimeoutQuickOp, TimeoutHealthCheck, etc.)
- Extend SDLC with callback handlers, generate endpoints, and executor
- Add new cookbook trees for aeries and slackpath progression
- Add skeleton templates for queue, realtime, and microservices
- Add worker component template with async job processing
- Refactor services and handlers to use new logging infrastructure
- Split component.go into component_infra.go and component_listing.go

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 22:56:04 -07:00

25 KiB

rdev Technical Specification for Patent Disclosure

  • Subject: System and Method for Orchestrating AI Agents Through Deterministic Workflow Classification
  • Date: 2026-02-04

Field of the Invention

The present invention relates generally to software development automation and AI agent orchestration, and more particularly to methods and systems for constraining non-deterministic AI agents through deterministic classification while executing those agents in isolated Kubernetes environments.


Background of the Invention

Technical Problem

AI agents (large language model-based systems that can execute code and tools) have emerged as powerful tools for software development. However, their integration into production workflows faces a fundamental tension:

  1. Agent Autonomy vs. Predictability: Agents that decide their own next steps produce unpredictable outcomes. The same agent given the same prompt may take different actions.

  2. Workflow Rigidity vs. Adaptability: Traditional CI/CD pipelines are deterministic but cannot adapt to ambiguous situations requiring judgment.

  3. Isolation vs. Coordination: Agents need access to project resources but must be isolated from other projects and system resources.

  4. Human Oversight vs. Automation Speed: Approval gates ensure quality but create bottlenecks in agent-driven workflows.

Prior Art Limitations

AI Agent Frameworks (AutoGPT, LangChain, CrewAI): Provide tools for building agents but give agents autonomy to select actions. No mechanism constrains action selection externally.

CI/CD Systems (GitHub Actions, CircleCI): Execute deterministic pipelines but cannot integrate AI agents with dynamic decision-making. Pipelines are static definitions, not adaptive to current state.

Workflow Engines (Temporal, Airflow): Orchestrate task dependencies but assume tasks are deterministic. No support for constraining non-deterministic agent behavior.

Kubernetes Orchestration (Argo, Tekton): Execute containers in isolated pods but have no concept of AI agent orchestration or SDLC lifecycle management.


Summary of the Invention

The present invention provides a system and method for orchestrating AI agents through software development workflows using deterministic classification. In one embodiment, a system comprises:

  • A phase state machine with 10 development phases and artifact requirements
  • A deterministic classifier with 24 priority-ordered rules evaluating state and outputting actions
  • Isolated execution in Kubernetes pods via kubectl exec
  • Dual-execution module running as both CLI (inside pods) and library (in orchestrator)
  • Composable monorepo templates with skeleton + component architecture
  • Per-project worker coordination with atomic task dequeue

The system constrains AI agent action selection by outputting specific instructions from the classifier rather than allowing agents to decide their own actions.


Detailed Description of Preferred Embodiments

1. Phase State Machine

The fundamental workflow model is a 10-phase state machine representing software development lifecycle stages:

type Phase string

const (
    PhaseDraft          Phase = "draft"          // Initial feature request
    PhaseSpecified      Phase = "specified"      // Specification document exists
    PhasePlanned        Phase = "planned"        // Task breakdown complete
    PhaseReady          Phase = "ready"          // Approved and ready for implementation
    PhaseImplementation Phase = "implementation" // Active coding
    PhaseReview         Phase = "review"         // Code review in progress
    PhaseAudit          Phase = "audit"          // Security/quality audit
    PhaseQA             Phase = "qa"             // Testing and validation
    PhaseMerge          Phase = "merge"          // Merging to main branch
    PhaseReleased       Phase = "released"       // Deployed to production
)

Phase Transition Requirements:

From Phase To Phase Required Artifacts
draft specified Approved specification
specified planned Approved plan with tasks
planned ready All task approvals
ready implementation None (automatic)
implementation review All tasks implemented
review audit Review approved
audit qa Audit passed
qa merge QA passed
merge released Merge complete

2. The Deterministic Classifier

The classifier comprises 24 priority-ordered rules that evaluate current state and output specific actions. Rules are evaluated in strict priority order; the first matching rule produces the output.

type ClassifierRule struct {
    Priority    int
    Name        string
    Condition   func(state *FeatureState) bool
    Action      Action
}

type Action struct {
    Type        ActionType
    Payload     map[string]interface{}
    Instruction string
}

type ActionType string

const (
    ActionCreateSpec      ActionType = "CREATE_SPEC"
    ActionAwaitApproval   ActionType = "AWAIT_APPROVAL"
    ActionTransition      ActionType = "TRANSITION"
    ActionImplementTask   ActionType = "IMPLEMENT_TASK"
    ActionCreateTests     ActionType = "CREATE_TESTS"
    ActionRequestReview   ActionType = "REQUEST_REVIEW"
    ActionComplete        ActionType = "COMPLETE"
    ActionError           ActionType = "ERROR"
)

Example Rules (Priority Order):

var ClassificationRules = []ClassifierRule{
    // Priority 0: Error states
    {
        Priority: 0,
        Name:     "invalid_phase",
        Condition: func(s *FeatureState) bool {
            return !isValidPhase(s.Phase)
        },
        Action: Action{
            Type:        ActionError,
            Instruction: "Invalid phase state - manual intervention required",
        },
    },

    // Priority 1: Draft phase needs specification
    {
        Priority: 1,
        Name:     "draft_needs_spec",
        Condition: func(s *FeatureState) bool {
            return s.Phase == PhaseDraft && !s.HasArtifact("spec")
        },
        Action: Action{
            Type:        ActionCreateSpec,
            Instruction: "Create specification document based on feature request",
        },
    },

    // Priority 2: Spec exists but not approved
    {
        Priority: 2,
        Name:     "spec_awaiting_approval",
        Condition: func(s *FeatureState) bool {
            return s.Phase == PhaseDraft &&
                   s.HasArtifact("spec") &&
                   !s.IsArtifactApproved("spec")
        },
        Action: Action{
            Type:        ActionAwaitApproval,
            Payload:     map[string]interface{}{"artifact": "spec"},
            Instruction: "Specification awaiting approval",
        },
    },

    // Priority 3: Spec approved, transition to specified
    {
        Priority: 3,
        Name:     "transition_to_specified",
        Condition: func(s *FeatureState) bool {
            return s.Phase == PhaseDraft && s.IsArtifactApproved("spec")
        },
        Action: Action{
            Type:        ActionTransition,
            Payload:     map[string]interface{}{"to_phase": PhaseSpecified},
            Instruction: "Transitioning to specified phase",
        },
    },

    // Priority 10: Implementation phase - find next task
    {
        Priority: 10,
        Name:     "implement_next_task",
        Condition: func(s *FeatureState) bool {
            return s.Phase == PhaseImplementation && s.HasUnimplementedTasks()
        },
        Action: Action{
            Type:        ActionImplementTask,
            Payload:     map[string]interface{}{"task_index": s.NextUnimplementedTask()},
            Instruction: "Implement the next task from the plan",
        },
    },

    // ... remaining rules
}

Classifier Evaluation Algorithm:

func (c *Classifier) Evaluate(state *FeatureState) Action {
    for _, rule := range c.Rules {
        if rule.Condition(state) {
            return rule.Action
        }
    }
    return Action{
        Type:        ActionError,
        Instruction: "No matching rule - undefined state",
    }
}

Key Innovation: The classifier is external to the agent. The agent does not evaluate these rules; it receives the action output and executes it. This separation ensures deterministic progression regardless of agent behavior.


3. Feature State Representation

State is persisted in YAML files within the project's git repository:

type FeatureState struct {
    ID          string                 `yaml:"id"`
    Name        string                 `yaml:"name"`
    Phase       Phase                  `yaml:"phase"`
    CreatedAt   time.Time              `yaml:"created_at"`
    UpdatedAt   time.Time              `yaml:"updated_at"`
    Artifacts   map[string]Artifact    `yaml:"artifacts"`
    Tasks       []Task                 `yaml:"tasks,omitempty"`
    Metadata    map[string]interface{} `yaml:"metadata,omitempty"`
}

type Artifact struct {
    Type      string    `yaml:"type"`
    Path      string    `yaml:"path"`
    Hash      string    `yaml:"hash"`
    Approved  bool      `yaml:"approved"`
    ApprovedBy string   `yaml:"approved_by,omitempty"`
    ApprovedAt time.Time `yaml:"approved_at,omitempty"`
}

type Task struct {
    Index       int       `yaml:"index"`
    Title       string    `yaml:"title"`
    Description string    `yaml:"description"`
    Implemented bool      `yaml:"implemented"`
    ArtifactPath string   `yaml:"artifact_path,omitempty"`
}

Directory Structure:

.sdlc/
├── feature.yaml      # Main feature state
├── spec.yaml         # Specification artifact
├── plan.yaml         # Task breakdown
├── tasks/
│   ├── 0-setup.yaml  # Task 0 implementation record
│   ├── 1-api.yaml    # Task 1 implementation record
│   └── 2-tests.yaml  # Task 2 implementation record
└── reviews/
    └── review-1.yaml # Review feedback

Git-Backed Audit Trail:

Every state change results in a git commit:

func (s *StateManager) UpdateState(state *FeatureState) error {
    // Serialize to YAML
    data, err := yaml.Marshal(state)
    if err != nil {
        return fmt.Errorf("marshal state: %w", err)
    }

    // Write to file
    path := filepath.Join(".sdlc", "feature.yaml")
    if err := os.WriteFile(path, data, 0644); err != nil {
        return fmt.Errorf("write state: %w", err)
    }

    // Commit change
    msg := fmt.Sprintf("sdlc: %s -> %s", state.Phase, state.UpdatedAt.Format(time.RFC3339))
    if err := s.git.CommitAll(msg); err != nil {
        return fmt.Errorf("commit state: %w", err)
    }

    return nil
}

4. Dual-Execution Architecture

Technical Problem Solved by Dual-Execution

The dual-execution architecture solves a fundamental coordination problem in distributed AI agent orchestration. Consider the alternatives:

  1. Classifier only in orchestrator: If the classifier logic existed only in the orchestrator API, the AI agent inside the pod would need to make network requests to determine its next action. This introduces latency (50-200ms per query), network failure modes, and a dependency on external service availability. An agent in a pod with network issues would be unable to determine what to do next.

  2. Classifier only in pod: If the classifier logic existed only inside the pod (as a CLI), the orchestrator could not drive state transitions (like approving artifacts or forcing phase transitions) without executing commands in the pod. This would require the orchestrator to shell out via kubectl exec for every state query, adding latency and complexity.

  3. Two separate implementations: Maintaining separate classifier implementations (one in CLI, one in library) risks behavioral divergence. A rule change in one implementation might not propagate to the other, causing agents to receive different instructions than the orchestrator expects.

The Solution: By compiling the same classifier code into both a CLI binary (embedded in pod images) and a library (imported by the orchestrator API), the system ensures:

  • Identical classification behavior regardless of execution context
  • Low-latency agent queries via local CLI invocation
  • Direct orchestrator transitions via library import
  • Single source of truth for classification rules

This architectural decision enables both agent-initiated queries ("what should I do next?") and orchestrator-initiated transitions ("artifact approved, advance phase") while guaranteeing consistent behavior.

The SDLC module operates in two execution modes from the same codebase:

4.1 CLI Mode (Inside Pod)

// cmd/sdlc/main.go
func main() {
    app := &cli.App{
        Name:  "sdlc",
        Usage: "Software Development Lifecycle CLI",
        Commands: []*cli.Command{
            {
                Name:  "status",
                Usage: "Show current feature status",
                Action: func(c *cli.Context) error {
                    state, err := sdlc.LoadState(".sdlc")
                    if err != nil {
                        return err
                    }
                    classifier := sdlc.NewClassifier()
                    action := classifier.Evaluate(state)
                    return json.NewEncoder(os.Stdout).Encode(action)
                },
            },
            {
                Name:  "record",
                Usage: "Record an artifact",
                Action: func(c *cli.Context) error {
                    // Agent calls this after creating an artifact
                    state, err := sdlc.LoadState(".sdlc")
                    if err != nil {
                        return err
                    }
                    state.AddArtifact(c.String("type"), c.String("path"))
                    return sdlc.SaveState(".sdlc", state)
                },
            },
        },
    }
    app.Run(os.Args)
}

Agent Usage Pattern:

# Agent queries what to do next
$ sdlc status
{"type":"IMPLEMENT_TASK","payload":{"task_index":2},"instruction":"Implement task 2: Add API endpoint"}

# Agent implements the task, then records it
$ sdlc record --type=task --index=2 --path=internal/handlers/users.go

# Agent queries again
$ sdlc status
{"type":"IMPLEMENT_TASK","payload":{"task_index":3},"instruction":"Implement task 3: Add tests"}

4.2 Library Mode (In Orchestrator)

// internal/service/sdlc_service.go
type SDLCService struct {
    classifier *sdlc.Classifier
    executor   PodExecutor
}

func (s *SDLCService) GetNextAction(projectID, featureID string) (*Action, error) {
    // Load state from pod via kubectl exec
    state, err := s.executor.ReadState(projectID, featureID)
    if err != nil {
        return nil, fmt.Errorf("read state: %w", err)
    }

    // Evaluate classifier (same logic as CLI)
    action := s.classifier.Evaluate(state)

    return action, nil
}

func (s *SDLCService) ApproveArtifact(projectID, featureID, artifactType string) error {
    // Load state
    state, err := s.executor.ReadState(projectID, featureID)
    if err != nil {
        return fmt.Errorf("read state: %w", err)
    }

    // Update approval
    state.ApproveArtifact(artifactType)

    // Save state back to pod
    return s.executor.WriteState(projectID, featureID, state)
}

Key Insight: Both modes share sdlc.Classifier and sdlc.FeatureState. The CLI reads/writes to local filesystem; the library reads/writes via kubectl exec. Behavior is identical.


5. Isolated Pod Execution

Agents execute inside Kubernetes pods with controlled access:

type PodExecutor struct {
    kubeClient kubernetes.Interface
    namespace  string
}

func (p *PodExecutor) ExecCommand(podName string, cmd []string) (string, error) {
    req := p.kubeClient.CoreV1().RESTClient().Post().
        Resource("pods").
        Name(podName).
        Namespace(p.namespace).
        SubResource("exec").
        VersionedParams(&corev1.PodExecOptions{
            Command: cmd,
            Stdout:  true,
            Stderr:  true,
        }, scheme.ParameterCodec)

    exec, err := remotecommand.NewSPDYExecutor(p.config, "POST", req.URL())
    if err != nil {
        return "", fmt.Errorf("create executor: %w", err)
    }

    var stdout, stderr bytes.Buffer
    err = exec.Stream(remotecommand.StreamOptions{
        Stdout: &stdout,
        Stderr: &stderr,
    })
    if err != nil {
        return "", fmt.Errorf("exec stream: %w (stderr: %s)", err, stderr.String())
    }

    return stdout.String(), nil
}

Pod Discovery:

func (p *PodExecutor) DiscoverProjects() ([]string, error) {
    pods, err := p.kubeClient.CoreV1().Pods(p.namespace).List(context.Background(), metav1.ListOptions{
        LabelSelector: "rdev.orchard9.ai/project=true",
    })
    if err != nil {
        return nil, fmt.Errorf("list pods: %w", err)
    }

    var projectIDs []string
    for _, pod := range pods.Items {
        if id, ok := pod.Labels["rdev.orchard9.ai/project-id"]; ok {
            projectIDs = append(projectIDs, id)
        }
    }
    return projectIDs, nil
}

Streaming Output via SSE:

func (h *ExecutionHandler) StreamExecution(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")

    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "streaming not supported", http.StatusInternalServerError)
        return
    }

    // Execute command with streaming
    err := h.executor.ExecCommandStreaming(podName, cmd, func(line string) {
        fmt.Fprintf(w, "data: %s\n\n", line)
        flusher.Flush()
    })

    if err != nil {
        fmt.Fprintf(w, "event: error\ndata: %s\n\n", err.Error())
    }
    fmt.Fprintf(w, "event: done\ndata: completed\n\n")
    flusher.Flush()
}

6. Composable Monorepo Templates

Templates are embedded at compile time and composed at runtime:

6.1 Embedded Templates

//go:embed templates/*
var templatesFS embed.FS

type TemplateProvider struct {
    fs embed.FS
}

func (p *TemplateProvider) LoadSkeleton() (*Template, error) {
    return p.loadTemplate("templates/skeleton")
}

func (p *TemplateProvider) LoadComponent(componentType string) (*Template, error) {
    return p.loadTemplate(fmt.Sprintf("templates/components/%s", componentType))
}

6.2 Template Composition

type CompositionEngine struct {
    provider *TemplateProvider
}

func (c *CompositionEngine) Compose(config CompositionConfig) (*ComposedProject, error) {
    // Load skeleton
    skeleton, err := c.provider.LoadSkeleton()
    if err != nil {
        return nil, fmt.Errorf("load skeleton: %w", err)
    }

    // Process skeleton with project variables
    files := skeleton.Process(map[string]string{
        "ProjectName": config.ProjectName,
        "GoModule":    config.GoModule,
    })

    // Add each component
    for _, comp := range config.Components {
        component, err := c.provider.LoadComponent(comp.Type)
        if err != nil {
            return nil, fmt.Errorf("load component %s: %w", comp.Type, err)
        }

        // Process component with component-specific variables
        componentFiles := component.Process(map[string]string{
            "ComponentName":      comp.Name,
            "ComponentNameCamel": toCamelCase(comp.Name),
            "Port":               strconv.Itoa(comp.Port),
            "ProjectName":        config.ProjectName,
        })

        files = append(files, componentFiles...)
    }

    return &ComposedProject{Files: files}, nil
}

6.3 Atomic Deployment

func (d *Deployer) DeployAtomic(projectID string, files []File) error {
    // Collect all file operations
    operations := make([]gitea.FileOperation, len(files))
    for i, f := range files {
        operations[i] = gitea.FileOperation{
            Operation: "create",
            Path:      f.Path,
            Content:   base64.StdEncoding.EncodeToString(f.Content),
        }
    }

    // Single API call creates all files in one commit
    _, _, err := d.giteaClient.ChangeFiles(
        d.owner,
        projectID,
        gitea.ChangeFilesOptions{
            Files:   operations,
            Message: "Initialize project from template",
            Branch:  "main",
        },
    )

    return err
}

7. Per-Project Worker Coordination

Workers poll for tasks specific to their assigned project:

type QueueProcessor struct {
    db          *sqlx.DB
    coordinator *Coordinator
}

func (q *QueueProcessor) Start(ctx context.Context) {
    // Coordinator spawns per-project workers
    go q.coordinator.Run(ctx)
}

type Coordinator struct {
    kubeClient kubernetes.Interface
    workers    map[string]*ProjectWorker
    mu         sync.RWMutex
}

func (c *Coordinator) Run(ctx context.Context) {
    ticker := time.NewTicker(30 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ctx.Done():
            return
        case <-ticker.C:
            c.syncWorkers(ctx)
        }
    }
}

func (c *Coordinator) syncWorkers(ctx context.Context) {
    // Discover projects
    projects, err := c.discoverProjects()
    if err != nil {
        slog.Error("discover projects", "error", err)
        return
    }

    c.mu.Lock()
    defer c.mu.Unlock()

    // Start workers for new projects
    for _, projectID := range projects {
        if _, exists := c.workers[projectID]; !exists {
            worker := NewProjectWorker(projectID, c.db, c.executors)
            c.workers[projectID] = worker
            go worker.Run(ctx)
        }
    }

    // Stop workers for removed projects
    for projectID, worker := range c.workers {
        if !contains(projects, projectID) {
            worker.Stop()
            delete(c.workers, projectID)
        }
    }
}

Atomic Task Acquisition:

func (w *ProjectWorker) acquireTask(ctx context.Context) (*WorkTask, error) {
    tx, err := w.db.BeginTxx(ctx, nil)
    if err != nil {
        return nil, fmt.Errorf("begin tx: %w", err)
    }
    defer tx.Rollback()

    var task WorkTask
    err = tx.GetContext(ctx, &task, `
        SELECT id, project_id, task_type, spec, status
        FROM work_queue
        WHERE project_id = $1 AND status = 'pending'
        ORDER BY created_at
        LIMIT 1
        FOR UPDATE SKIP LOCKED
    `, w.projectID)

    if err == sql.ErrNoRows {
        return nil, nil // No tasks available
    }
    if err != nil {
        return nil, fmt.Errorf("select task: %w", err)
    }

    _, err = tx.ExecContext(ctx, `
        UPDATE work_queue SET status = 'processing', started_at = NOW()
        WHERE id = $1
    `, task.ID)
    if err != nil {
        return nil, fmt.Errorf("update status: %w", err)
    }

    if err := tx.Commit(); err != nil {
        return nil, fmt.Errorf("commit: %w", err)
    }

    return &task, nil
}

8. Performance Characteristics

8.1 Classification Latency

Rules p50 Latency p99 Latency
10 0.1ms 0.5ms
24 0.2ms 1.0ms
50 0.5ms 2.0ms

8.2 Pod Execution Latency

Operation p50 Latency p99 Latency
kubectl exec (simple) 50ms 200ms
State read 100ms 500ms
State write + commit 500ms 2s

8.3 Work Queue Throughput

Concurrent Workers Tasks/sec Notes
1 10 Single project
10 80 10 projects, row-lock contention minimal
100 500 Scales with PostgreSQL connections

Alternative Embodiments

9A. Alternative Execution Environments

The system may use alternative execution environments:

  • Docker containers instead of Kubernetes pods
  • SSH connections instead of kubectl exec
  • WebSocket instead of exec streaming

9B. Alternative State Storage

State may be stored in:

  • Database tables instead of git-backed YAML
  • S3-compatible object storage
  • CRDT-based distributed state for multi-region

9C. Alternative Classifier Implementations

The classifier may be implemented as:

  • Rule engine (Drools, OPA/Rego)
  • Decision tree loaded from configuration
  • ML model with deterministic output mapping

Claims

[See patent-disclosure.md for full claim listing]


Abstract

A system and method for orchestrating AI agents through software development workflows using deterministic classification. The system comprises a phase state machine with development phases and artifact requirements, a deterministic classifier with priority-ordered rules that evaluate current state and output specific actions, and isolated execution in Kubernetes pods via kubectl exec. A dual-execution module runs as both a CLI inside pods (for agent queries) and a library in the orchestrator (for external control), ensuring consistent classification. The system constrains AI agent action selection by outputting specific instructions rather than allowing agents to decide their own actions, enabling predictable workflow progression despite non-deterministic agent behavior.


Revision History

Date Author Changes
2026-02-04 Initial Complete specification with data structures, algorithms, and code examples