Skip to content

Gesamtarchitektur & Einbettung in SIN‑Code Die neue Spec‑Layer #122

Description

@Delqhi

📋 SIN‑Code × Spec Framework Fusion – State of the Future Plan

Nach der intensiven Analyse aller genannten Repositories und einem erneuten Deep‑Dive in SIN‑Code wird klar: Sie besitzen bereits eine der fortschrittlichsten Architekturen für AI‑Coding‑Assistenten. Was fehlt, ist eine strukturierte, deterministische Spezifikations‑Ebene, die die bestehende „verification‑first“‑Philosophie mit „spec‑first“‑Disziplin verbindet. Der folgende Plan zeigt, wie Sie die besten Ideen von Spectr, SpecD, SDLC, MetaSpec und SpecKit in SIN‑Code integrieren – mit vollständigem, direkt nutzbarem Code.

🧭 Kapitelübersicht

  1. Architektur‑Überblick – Die grosse Vision
  2. Phase 1: Spezifikations‑Backbone (Spectr‑Port)
  3. Phase 2: Deterministische Spec‑Compilation (SpecD‑Port)
  4. Phase 3: Quality Gates & Agentische Pipeline (SDLC‑Integration)
  5. Phase 4: MetaSpec‑Integration & Token‑Optimierung
  6. Phase 5: Spec‑Kit‑Stil Slash‑Commands & Spezifikations‑UI
  7. Gesamtarchitektur & Einbettung in SIN‑Code
  8. Rollout‑Plan & Abschlussbemerkung

1. Architektur‑Überblick – Die grosse Vision

Die neue Architektur fügt eine vollständige Spec‑Driven‑Development‑Schicht hinzu, die nahtlos mit SIN‑Codes bestehendem Agent‑Loop zusammenarbeitet:

┌─────────────────────────────────────────────────────────────────────────────┐
│                         SIN‑CODE – Erweiterte Architektur                    │
├─────────────────────────────────────────────────────────────────────────────┤
│  CLI / TUI / WebUI                                                           │
│    │                                                                         │
│    ▼                                                                         │
│  ┌───────────────────────────────────────────────────────────────────────┐   │
│  │  NEU: SPEC‑LAYER (Go)                                                  │   │
│  │  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐   │   │
│  │  │  spectr     │ │  specd      │ │  sdlc       │ │  metaspec       │   │   │
│  │  │  (Backbone) │ │  (Compile)  │ │  (Gates)    │ │  (Generator)    │   │   │
│  │  └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘   │   │
│  │         │               │               │                  │           │   │
│  │         └───────────────┴───────────────┴──────────────────┘           │   │
│  │                                                                         │   │
│  │  spec‑repo/                                                             │   │
│  │  ├── specs/           ← Source of Truth                                 │   │
│  │  ├── changes/         ← Isolierte Arbeitsordner                         │   │
│  │  ├── .spec‑graph/     ← Index (Code + Specs)                            │   │
│  │  └── .spec‑hooks/     ← Pre/Post‑Hooks (Lint, Tests, Security)          │   │
│  └───────────────────────────────────────────────────────────────────────┘   │
│    │                                                                         │
│    ▼                                                                         │
│  ┌───────────────────────────────────────────────────────────────────────┐   │
│  │  BESTEHEND: Agent‑Loop (PLAN → ACT → VERIFY → DONE)                    │   │
│  │  • Provider (OpenAI‑kompatibel)                                        │   │
│  │  • Permission (allow/ask/deny, M4)                                     │   │
│  │  • Hooks (24 Events)                                                   │   │
│  │  • Verify Gate (PoC/Oracle, M3)                                        │   │
│  │  • Lessons (Closed Learning Loop)                                      │   │
│  │  • Sessions (SQLite)                                                   │   │
│  │  • Swarm Mode (N Profile)                                              │   │
│  └───────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘

Die zentrale Idee: Die Spec‑Layer wird zum planenden Gehirn, während der Agent‑Loop das ausführende Rückgrat bleibt. Beide kommunizieren über deterministische Schnittstellen – keine LLM‑Entscheidungen mehr über Spec‑Merges oder Änderungseinflüsse. Das ist genau die Lücke, die alle bisherigen Tools offen lassen.

"The right specs are compiled, not discovered." – SpecD

2. Phase 1 – Spektraler Spec‑Backbone – Port von Spectr

Spectr ist in Go geschrieben und damit die natürlichste Basis. Es bietet ein sauberes CLI für spec‑gesteuerte Entwicklung mit drei Phasen:

  1. Creating Changes – Proposals mit Delta‑Specs
  2. Implementing Changes – Checkliste abarbeiten
  3. Archiving Changes – Delta‑Merging der Specs

2.1 Installierte Pakete

# Neue interne Pakete
go get github.com/google/uuid
go get github.com/spf13/cobra  # besteht bereits
# Keine weiteren externen Abhängigkeiten – Spectr ist rein standard library

2.2 Kern‑Datenstrukturen

Datei: internal/spec/types.go

// Package spec implements the spec‑driven development backbone.
// Inspired by spectr (connerohnesorge/spectr) and ported to Go.
package spec

import (
    "encoding/json"
    "time"
)

// Entity types
const (
    TypeSpec   = "spec"
    TypeChange = "change"
    TypeDelta  = "delta"
)

// Spec represents the current state of a specification (source of truth).
type Spec struct {
    Path        string          `json:"path"`
    Name        string          `json:"name"`
    Content     string          `json:"content"`
    Version     string          `json:"version"`
    LastUpdated time.Time       `json:"last_updated"`
    Metadata    json.RawMessage `json:"metadata,omitempty"`
}

// Change represents an isolated change folder.
type Change struct {
    ID          string          `json:"id"`
    Path        string          `json:"path"`
    Title       string          `json:"title"`
    Description string          `json:"description"`
    Status      ChangeStatus    `json:"status"`
    CreatedAt   time.Time       `json:"created_at"`
    UpdatedAt   time.Time       `json:"updated_at"`
    Metadata    json.RawMessage `json:"metadata,omitempty"`
}

type ChangeStatus string

const (
    StatusDraft     ChangeStatus = "draft"
    StatusInReview  ChangeStatus = "in‑review"
    StatusApproved  ChangeStatus = "approved"
    StatusInProgress ChangeStatus = "in‑progress"
    StatusArchived  ChangeStatus = "archived"
    StatusRejected  ChangeStatus = "rejected"
)

// DeltaSpec represents a change delta.
type DeltaSpec struct {
    // Operation: ADDED, MODIFIED, REMOVED
    Operation   DeltaOp     `json:"operation"`
    Section     string      `json:"section"`
    OldContent  string      `json:"old_content,omitempty"`
    NewContent  string      `json:"new_content,omitempty"`
    ChangeID    string      `json:"change_id"`
}

type DeltaOp string

const (
    OpAdded    DeltaOp = "ADDED"
    OpModified DeltaOp = "MODIFIED"
    OpRemoved  DeltaOp = "REMOVED"
)

// ValidationReport holds the result of spec validation.
type ValidationReport struct {
    Valid   bool               `json:"valid"`
    Errors  []ValidationError  `json:"errors,omitempty"`
    Warnings []ValidationError `json:"warnings,omitempty"`
}

type ValidationError struct {
    Path    string `json:"path"`
    Line    int    `json:"line"`
    Message string `json:"message"`
    Level   string `json:"level"` // error, warning
}

2.3 Validator (Deterministisch – Keine LLM)

Datei: internal/spec/validate.go

package spec

import (
    "bufio"
    "fmt"
    "os"
    "regexp"
    "strings"
)

// ValidateSpec checks a spec file for structural correctness.
// This is 100% deterministic — no LLM involvement.
func ValidateSpec(path string) (*ValidationReport, error) {
    content, err := os.ReadFile(path)
    if err != nil {
        return nil, err
    }

    report := &ValidationReport{Valid: true}
    lines := strings.Split(string(content), "\n")
    inRequirement := false
    reqPattern := regexp.MustCompile(`^###?\s+Requirement:`)
    
    for i, line := range lines {
        trimmed := strings.TrimSpace(line)
        
        // Check for requirement headers
        if reqPattern.MatchString(line) {
            inRequirement = true
            // Ensure requirement has a description
            if i+1 >= len(lines) || strings.TrimSpace(lines[i+1]) == "" {
                report.Errors = append(report.Errors, ValidationError{
                    Path:    path,
                    Line:    i + 1,
                    Message: "Requirement header must be followed by description",
                    Level:   "error",
                })
                report.Valid = false
            }
            continue
        }
        
        // Check for orphaned "SHOULD" statements
        if inRequirement && strings.Contains(trimmed, "SHOULD") {
            if !strings.HasPrefix(trimmed, "-") && !strings.HasPrefix(trimmed, "*") {
                report.Warnings = append(report.Warnings, ValidationError{
                    Path:    path,
                    Line:    i + 1,
                    Message: "SHOULD statement should be in a list item (- or *)",
                    Level:   "warning",
                })
            }
        }
        
        // Check for empty sections
        if strings.HasPrefix(line, "##") && i+1 < len(lines) && 
           strings.TrimSpace(lines[i+1]) == "" && 
           !strings.HasPrefix(lines[i+2], "##") {
            report.Warnings = append(report.Warnings, ValidationError{
                Path:    path,
                Line:    i + 1,
                Message: "Empty section after header",
                Level:   "warning",
            })
        }
    }
    
    return report, nil
}

// ValidateDelta checks a delta specification for correctness.
func ValidateDelta(delta *DeltaSpec) error {
    if delta.ChangeID == "" {
        return fmt.Errorf("delta missing change_id")
    }
    if delta.Section == "" {
        return fmt.Errorf("delta missing section")
    }
    switch delta.Operation {
    case OpAdded, OpModified, OpRemoved:
        // valid
    default:
        return fmt.Errorf("unknown operation: %s", delta.Operation)
    }
    if delta.Operation == OpAdded && delta.NewContent == "" {
        return fmt.Errorf("ADDED operation requires new_content")
    }
    if delta.Operation == OpRemoved && delta.OldContent == "" {
        return fmt.Errorf("REMOVED operation requires old_content")
    }
    return nil
}

2.4 Delta‑Merger (Deterministisch)

Datei: internal/spec/merge.go

package spec

import (
    "fmt"
    "os"
    "strings"
)

// MergeDeltas applies a list of deltas to the base spec.
// This is deterministic and does NOT use LLM for merging.
func MergeDeltas(baseContent string, deltas []DeltaSpec) (string, error) {
    lines := strings.Split(baseContent, "\n")
    result := make([]string, 0, len(lines))
    
    // Build section index
    sections := make(map[string][]int)
    currentSection := ""
    for i, line := range lines {
        if strings.HasPrefix(line, "##") {
            currentSection = strings.TrimSpace(strings.TrimPrefix(line, "##"))
        }
        sections[currentSection] = append(sections[currentSection], i)
    }
    
    // Group deltas by section
    deltasBySection := make(map[string][]DeltaSpec)
    for _, delta := range deltas {
        deltasBySection[delta.Section] = append(deltasBySection[delta.Section], delta)
    }
    
    // Process each line
    for i, line := range lines {
        // Check if we're entering a section with pending modifications
        if strings.HasPrefix(line, "##") {
            section := strings.TrimSpace(strings.TrimPrefix(line, "##"))
            if deltas, ok := deltasBySection[section]; ok {
                for _, delta := range deltas {
                    switch delta.Operation {
                    case OpAdded:
                        result = append(result, line)
                        result = append(result, delta.NewContent)
                        // Skip original content for this section
                        i = skipSection(lines, i)
                        continue
                    case OpModified:
                        // Replace the entire section content
                        result = append(result, line)
                        result = append(result, delta.NewContent)
                        i = skipSection(lines, i)
                        continue
                    case OpRemoved:
                        // Skip the entire section
                        i = skipSection(lines, i)
                        continue
                    }
                }
            }
        }
        result = append(result, line)
    }
    
    return strings.Join(result, "\n"), nil
}

func skipSection(lines []string, start int) int {
    for i := start + 1; i < len(lines); i++ {
        if strings.HasPrefix(lines[i], "##") {
            return i - 1
        }
    }
    return len(lines) - 1
}

2.5 CLI‑Integration

Datei: cmd/sin-code/spec_cmd.go

package main

import (
    "encoding/json"
    "fmt"
    "os"
    
    "github.com/OpenSIN-Code/SIN-Code/internal/spec"
    "github.com/spf13/cobra"
)

var specCmd = &cobra.Command{
    Use:   "spec",
    Short: "Spec‑driven development commands",
    Long:  "Manage specifications, changes, and delta merging.",
}

var specInitCmd = &cobra.Command{
    Use:   "init",
    Short: "Initialize spec directory structure",
    RunE: func(cmd *cobra.Command, args []string) error {
        dirs := []string{
            "specs",
            "changes",
            "changes/archive",
            ".spec‑graph",
            ".spec‑hooks",
        }
        for _, dir := range dirs {
            if err := os.MkdirAll(dir, 0755); err != nil {
                return fmt.Errorf("failed to create %s: %w", dir, err)
            }
        }
        
        // Create example spec
        exampleSpec := `# API Specification

## Authentication
### Requirement: JWT tokens
SHOULD expire after 1 hour
SHOULD be refreshable

## Rate Limiting
### Requirement: Per‑user limits
SHOULD allow 100 requests per minute
SHOULD return 429 when exceeded
`
        if err := os.WriteFile("specs/api.md", []byte(exampleSpec), 0644); err != nil {
            return err
        }
        
        fmt.Println("✅ Spec directory initialized.")
        fmt.Println("   Created: specs/, changes/, .spec‑graph/")
        fmt.Println("   Example spec: specs/api.md")
        return nil
    },
}

var specValidateCmd = &cobra.Command{
    Use:   "validate [path]",
    Short: "Validate a spec file",
    Args:  cobra.ExactArgs(1),
    RunE: func(cmd *cobra.Command, args []string) error {
        report, err := spec.ValidateSpec(args[0])
        if err != nil {
            return err
        }
        
        output, _ := cmd.Flags().GetBool("json")
        if output {
            enc := json.NewEncoder(os.Stdout)
            enc.SetIndent("", "  ")
            return enc.Encode(report)
        }
        
        if report.Valid {
            fmt.Printf("✅ %s is valid\n", args[0])
        } else {
            fmt.Printf("❌ %s has errors:\n", args[0])
            for _, err := range report.Errors {
                fmt.Printf("   %s:%d: %s\n", err.Path, err.Line, err.Message)
            }
        }
        for _, warn := range report.Warnings {
            fmt.Printf("   ⚠️  %s:%d: %s\n", warn.Path, warn.Line, warn.Message)
        }
        return nil
    },
}

var specChangeCreateCmd = &cobra.Command{
    Use:   "create <name>",
    Short: "Create a new change",
    Args:  cobra.ExactArgs(1),
    RunE: func(cmd *cobra.Command, args []string) error {
        change := &spec.Change{
            ID:        generateChangeID(args[0]),
            Path:      fmt.Sprintf("changes/%s", args[0]),
            Title:     args[0],
            Status:    spec.StatusDraft,
            CreatedAt: time.Now(),
        }
        
        // Create directory structure
        if err := os.MkdirAll(change.Path, 0755); err != nil {
            return err
        }
        
        // Write change metadata
        data, _ := json.MarshalIndent(change, "", "  ")
        if err := os.WriteFile(fmt.Sprintf("%s/change.json", change.Path), data, 0644); err != nil {
            return err
        }
        
        // Create spec delta template
        deltaTemplate := `## ADDED Requirements
### Requirement: ` + args[0] + `
SHOULD be implemented according to specifications
`
        if err := os.WriteFile(fmt.Sprintf("%s/specs.md", change.Path), []byte(deltaTemplate), 0644); err != nil {
            return err
        }
        
        // Create task checklist
        tasks := `# Implementation Tasks

- [ ] 1. Review requirements in specs.md
- [ ] 2. Design solution (update design.md)
- [ ] 3. Implement code
- [ ] 4. Write tests
- [ ] 5. Update documentation
- [ ] 6. Verify with sin-code verify
`
        if err := os.WriteFile(fmt.Sprintf("%s/tasks.md", change.Path), []byte(tasks), 0644); err != nil {
            return err
        }
        
        fmt.Printf("✅ Created change: %s\n", change.ID)
        fmt.Printf("   Path: %s\n", change.Path)
        fmt.Printf("   Next: sin spec apply %s\n", change.ID)
        return nil
    },
}

var specChangeArchiveCmd = &cobra.Command{
    Use:   "archive <change‑id>",
    Short: "Archive a completed change and merge deltas",
    Args:  cobra.ExactArgs(1),
    RunE: func(cmd *cobra.Command, args []string) error {
        changeID := args[0]
        changePath := fmt.Sprintf("changes/%s", changeID)
        
        // Read and parse deltas
        deltaContent, err := os.ReadFile(fmt.Sprintf("%s/specs.md", changePath))
        if err != nil {
            return err
        }
        
        deltas, err := parseDeltas(string(deltaContent), changeID)
        if err != nil {
            return err
        }
        
        // Merge each delta into its target spec
        for specPath, specDeltas := range groupDeltasBySpec(deltas) {
            baseContent, err := os.ReadFile(specPath)
            if err != nil {
                // Spec doesn't exist yet for ADDED deltas
                baseContent = []byte{}
            }
            
            newContent, err := spec.MergeDeltas(string(baseContent), specDeltas)
            if err != nil {
                return fmt.Errorf("merge failed for %s: %w", specPath, err)
            }
            
            if err := os.WriteFile(specPath, []byte(newContent), 0644); err != nil {
                return err
            }
            fmt.Printf("   ✓ Updated %s\n", specPath)
        }
        
        // Move to archive
        archivePath := fmt.Sprintf("changes/archive/%s‑%s", 
            time.Now().Format("2006‑01‑02"), changeID)
        if err := os.Rename(changePath, archivePath); err != nil {
            return err
        }
        
        fmt.Printf("✅ Archived change: %s → %s\n", changeID, archivePath)
        return nil
    },
}

// Helper functions
func generateChangeID(name string) string {
    return strings.ToLower(strings.ReplaceAll(name, " ", "-"))
}

func parseDeltas(content, changeID string) ([]spec.DeltaSpec, error) {
    // Parse markdown deltas with ## ADDED/MODIFIED/REMOVED headers
    var deltas []spec.DeltaSpec
    lines := strings.Split(content, "\n")
    
    for i, line := range lines {
        if strings.HasPrefix(line, "## ADDED") {
            section := strings.TrimSpace(strings.TrimPrefix(line, "## ADDED"))
            delta := spec.DeltaSpec{
                Operation: spec.OpAdded,
                Section:   section,
                ChangeID:  changeID,
            }
            // Collect content until next section
            var contentLines []string
            for j := i + 1; j < len(lines) && !strings.HasPrefix(lines[j], "##"); j++ {
                contentLines = append(contentLines, lines[j])
            }
            delta.NewContent = strings.Join(contentLines, "\n")
            deltas = append(deltas, delta)
        }
        // Similar for MODIFIED and REMOVED...
    }
    return deltas, nil
}

func groupDeltasBySpec(deltas []spec.DeltaSpec) map[string][]spec.DeltaSpec {
    result := make(map[string][]spec.DeltaSpec)
    for _, d := range deltas {
        // Map section to file path (simplified)
        specPath := fmt.Sprintf("specs/%s.md", strings.ToLower(d.Section))
        result[specPath] = append(result[specPath], d)
    }
    return result
}

func init() {
    specValidateCmd.Flags().Bool("json", false, "Output as JSON")
    
    specCmd.AddCommand(specInitCmd)
    specCmd.AddCommand(specValidateCmd)
    specCmd.AddCommand(specChangeCreateCmd)
    specCmd.AddCommand(specChangeArchiveCmd)
}

Dieser spectr‑Port liefert das vollständige Gerüst für spec‑gesteuerte Entwicklung – komplett in Go, ohne LLM‑Abhängigkeiten, mit deterministischem Merging und klarem CLI. Es ist die solide Grundlage für alles Weitere.

3. Phase 2 – Deterministische Spec‑Compilation – Port von SpecD

SpecD bringt das Konzept der "compiled context" und des Code‑Graphs. Der Agent entscheidet nicht, welche Specs relevant sind – das System berechnet es deterministisch. Zwei Kernkomponenten werden nach Go portiert: der Indexer (Code + Specs) und der Compiler (Context‑Assembly).

3.1 Code‑Graph Indexer

Datei: internal/spec/graph/indexer.go

// Package graph provides deterministic spec‑graph indexing.
package graph

import (
    "encoding/json"
    "os"
    "path/filepath"
    "regexp"
    "strings"
)

// Node represents a node in the spec‑graph.
type Node struct {
    ID       string            `json:"id"`
    Type     string            `json:"type"` // "spec", "file", "symbol", "dependency"
    Path     string            `json:"path"`
    Metadata map[string]string `json:"metadata,omitempty"`
}

// Edge represents a directed relationship.
type Edge struct {
    From   string `json:"from"`
    To     string `json:"to"`
    Type   string `json:"type"` // "references", "implements", "depends‑on"
}

// Graph holds the complete index.
type Graph struct {
    Nodes map[string]Node `json:"nodes"`
    Edges []Edge          `json:"edges"`
}

// Indexer builds the spec‑graph from a repository.
type Indexer struct {
    rootPath string
    graph    *Graph
    patterns []*regexp.Regexp
}

// NewIndexer creates a new indexer for the given root path.
func NewIndexer(rootPath string) *Indexer {
    return &Indexer{
        rootPath: rootPath,
        graph: &Graph{
            Nodes: make(map[string]Node),
            Edges: []Edge{},
        },
        patterns: []*regexp.Regexp{
            regexp.MustCompile(`\.go$`),
            regexp.MustCompile(`\.py$`),
            regexp.MustCompile(`\.ts$`),
            regexp.MustCompile(`\.rs$`),
        },
    }
}

// Index scans the repository and builds the graph.
func (idx *Indexer) Index() (*Graph, error) {
    // Index all spec files first (source of truth)
    if err := idx.indexSpecs(); err != nil {
        return nil, err
    }
    
    // Index all source files
    if err := idx.indexSources(); err != nil {
        return nil, err
    }
    
    // Build relationships
    if err := idx.buildRelationships(); err != nil {
        return nil, err
    }
    
    // Persist to disk
    return idx.graph, idx.persist()
}

func (idx *Indexer) indexSpecs() error {
    specPath := filepath.Join(idx.rootPath, "specs")
    return filepath.Walk(specPath, func(path string, info os.FileInfo, err error) error {
        if err != nil || info.IsDir() {
            return nil
        }
        if !strings.HasSuffix(path, ".md") {
            return nil
        }
        
        relPath, _ := filepath.Rel(idx.rootPath, path)
        node := Node{
            ID:   "spec:" + relPath,
            Type: "spec",
            Path: relPath,
        }
        idx.graph.Nodes[node.ID] = node
        return nil
    })
}

func (idx *Indexer) indexSources() error {
    return filepath.Walk(idx.rootPath, func(path string, info os.FileInfo, err error) error {
        if err != nil || info.IsDir() {
            return nil
        }
        
        // Skip .git, node_modules, etc.
        if strings.Contains(path, ".git") || strings.Contains(path, "node_modules") {
            return filepath.SkipDir
        }
        
        // Check if file extension matches
        matched := false
        for _, p := range idx.patterns {
            if p.MatchString(path) {
                matched = true
                break
            }
        }
        if !matched {
            return nil
        }
        
        relPath, _ := filepath.Rel(idx.rootPath, path)
        node := Node{
            ID:   "file:" + relPath,
            Type: "file",
            Path: relPath,
        }
        idx.graph.Nodes[node.ID] = node
        
        // Extract symbols (simplified)
        idx.extractSymbols(path, relPath)
        return nil
    })
}

func (idx *Indexer) extractSymbols(filePath, relPath string) {
    content, err := os.ReadFile(filePath)
    if err != nil {
        return
    }
    
    // Go function detection
    goFunc := regexp.MustCompile(`func\s+(\w+)\(`)
    for _, match := range goFunc.FindAllStringSubmatch(string(content), -1) {
        if len(match) > 1 {
            node := Node{
                ID:   "symbol:" + relPath + "#" + match[1],
                Type: "symbol",
                Path: relPath,
                Metadata: map[string]string{
                    "name": match[1],
                    "kind": "function",
                },
            }
            idx.graph.Nodes[node.ID] = node
            idx.graph.Edges = append(idx.graph.Edges, Edge{
                From: "file:" + relPath,
                To:   node.ID,
                Type: "declares",
            })
        }
    }
}

func (idx *Indexer) buildRelationships() error {
    // For each spec, find which files implement it
    for specID, specNode := range idx.graph.Nodes {
        if specNode.Type != "spec" {
            continue
        }
        
        // Simple heuristic: spec name maps to file basename
        baseName := strings.TrimSuffix(filepath.Base(specNode.Path), ".md")
        for fileID, fileNode := range idx.graph.Nodes {
            if fileNode.Type != "file" {
                continue
            }
            if strings.Contains(fileNode.Path, baseName) {
                idx.graph.Edges = append(idx.graph.Edges, Edge{
                    From: specID,
                    To:   fileID,
                    Type: "implements",
                })
            }
        }
    }
    return nil
}

func (idx *Indexer) persist() error {
    data, err := json.MarshalIndent(idx.graph, "", "  ")
    if err != nil {
        return err
    }
    graphDir := filepath.Join(idx.rootPath, ".spec‑graph")
    if err := os.MkdirAll(graphDir, 0755); err != nil {
        return err
    }
    return os.WriteFile(filepath.Join(graphDir, "index.json"), data, 0644)
}

3.2 Deterministischer Compiler

Datei: internal/spec/compiler.go

package spec

import (
    "fmt"
    "os"
    "path/filepath"
    "strings"
    
    "github.com/OpenSIN-Code/SIN-Code/internal/spec/graph"
)

// CompiledContext is the deterministic output for an agent.
type CompiledContext struct {
    ChangeID    string   `json:"change_id"`
    Specs       []string `json:"specs"`       // Full spec content
    RelevantPaths []string `json:"relevant_paths"`
    Tasks       []Task   `json:"tasks"`       // From tasks.md
    Hooks       []Hook   `json:"hooks"`       // Pre/post hooks
}

type Task struct {
    ID          string `json:"id"`
    Description string `json:"description"`
    Completed   bool   `json:"completed"`
}

type Hook struct {
    Event   string   `json:"event"`   // pre‑change, post‑implementation, pre‑archive
    Command string   `json:"command"`
    Args    []string `json:"args,omitempty"`
}

// Compiler builds a CompiledContext for a given change.
type Compiler struct {
    rootPath string
    graph    *graph.Graph
}

// NewCompiler creates a compiler for the given repository.
func NewCompiler(rootPath string) (*Compiler, error) {
    graphPath := filepath.Join(rootPath, ".spec‑graph", "index.json")
    data, err := os.ReadFile(graphPath)
    if err != nil {
        return nil, fmt.Errorf("graph not found, run `sin spec build‑graph` first: %w", err)
    }
    
    var g graph.Graph
    if err := json.Unmarshal(data, &g); err != nil {
        return nil, err
    }
    
    return &Compiler{
        rootPath: rootPath,
        graph:    &g,
    }, nil
}

// CompileForChange returns the deterministic context for a change.
func (c *Compiler) CompileForChange(changeID string) (*CompiledContext, error) {
    changePath := filepath.Join(c.rootPath, "changes", changeID)
    
    // 1. Read change metadata
    changeData, err := os.ReadFile(filepath.Join(changePath, "change.json"))
    if err != nil {
        return nil, err
    }
    var change Change
    if err := json.Unmarshal(changeData, &change); err != nil {
        return nil, err
    }
    
    // 2. Read delta specs (these are the requirements for this change)
    deltaContent, err := os.ReadFile(filepath.Join(changePath, "specs.md"))
    if err != nil {
        return nil, err
    }
    
    // 3. Compute which main specs are impacted
    impactedSpecs := c.computeImpactedSpecs(string(deltaContent))
    
    // 4. Read those spec files
    specs := make([]string, 0, len(impactedSpecs))
    for _, specPath := range impactedSpecs {
        content, err := os.ReadFile(filepath.Join(c.rootPath, specPath))
        if err != nil && !os.IsNotExist(err) {
            continue // Spec doesn't exist yet for ADDED
        }
        specs = append(specs, string(content))
    }
    
    // 5. Compute relevant files from code graph
    relevantPaths := c.computeRelevantPaths(impactedSpecs)
    
    // 6. Parse tasks.md
    tasks, err := c.parseTasks(changePath)
    if err != nil {
        return nil, err
    }
    
    // 7. Load hooks
    hooks, err := c.loadHooks(changePath)
    if err != nil {
        return nil, err
    }
    
    return &CompiledContext{
        ChangeID:      changeID,
        Specs:         specs,
        RelevantPaths: relevantPaths,
        Tasks:         tasks,
        Hooks:         hooks,
    }, nil
}

func (c *Compiler) computeImpactedSpecs(deltaContent string) []string {
    var impacted []string
    lines := strings.Split(deltaContent, "\n")
    
    for _, line := range lines {
        if strings.HasPrefix(line, "## ADDED") {
            section := strings.TrimSpace(strings.TrimPrefix(line, "## ADDED"))
            impacted = append(impacted, fmt.Sprintf("specs/%s.md", strings.ToLower(section)))
        }
        if strings.HasPrefix(line, "## MODIFIED") {
            section := strings.TrimSpace(strings.TrimPrefix(line, "## MODIFIED"))
            impacted = append(impacted, fmt.Sprintf("specs/%s.md", strings.ToLower(section)))
        }
    }
    return impacted
}

func (c *Compiler) computeRelevantPaths(specPaths []string) []string {
    relevant := make(map[string]bool)
    
    for _, specPath := range specPaths {
        specID := "spec:" + specPath
        // Find all files that implement this spec
        for _, edge := range c.graph.Edges {
            if edge.From == specID && edge.Type == "implements" {
                if node, ok := c.graph.Nodes[edge.To]; ok {
                    relevant[node.Path] = true
                }
            }
        }
        // Also find files that depend on those files
        for fileID := range relevant {
            for _, edge := range c.graph.Edges {
                if edge.From == fileID && edge.Type == "depends‑on" {
                    if node, ok := c.graph.Nodes[edge.To]; ok {
                        relevant[node.Path] = true
                    }
                }
            }
        }
    }
    
    result := make([]string, 0, len(relevant))
    for p := range relevant {
        result = append(result, p)
    }
    return result
}

func (c *Compiler) parseTasks(changePath string) ([]Task, error) {
    tasksPath := filepath.Join(changePath, "tasks.md")
    content, err := os.ReadFile(tasksPath)
    if err != nil {
        return nil, nil // No tasks yet
    }
    
    var tasks []Task
    lines := strings.Split(string(content), "\n")
    for _, line := range lines {
        if strings.HasPrefix(line, "- [ ]") {
            tasks = append(tasks, Task{
                ID:          fmt.Sprintf("task‑%d", len(tasks)+1),
                Description: strings.TrimSpace(strings.TrimPrefix(line, "- [ ]")),
                Completed:   false,
            })
        }
        if strings.HasPrefix(line, "- [x]") {
            tasks = append(tasks, Task{
                ID:          fmt.Sprintf("task‑%d", len(tasks)+1),
                Description: strings.TrimSpace(strings.TrimPrefix(line, "- [x]")),
                Completed:   true,
            })
        }
    }
    return tasks, nil
}

func (c *Compiler) loadHooks(changePath string) ([]Hook, error) {
    hooksPath := filepath.Join(changePath, "hooks.json")
    data, err := os.ReadFile(hooksPath)
    if err != nil {
        return nil, nil
    }
    var hooks []Hook
    if err := json.Unmarshal(data, &hooks); err != nil {
        return nil, err
    }
    return hooks, nil
}

// GenerateContextForAgent produces the exact string to inject into agent context.
func (c *Compiler) GenerateContextForAgent(changeID string) (string, error) {
    ctx, err := c.CompileForChange(changeID)
    if err != nil {
        return "", err
    }
    
    var sb strings.Builder
    sb.WriteString(fmt.Sprintf("# Spec Context for Change: %s\n\n", changeID))
    sb.WriteString("## Requirements\n")
    for _, spec := range ctx.Specs {
        sb.WriteString(spec)
        sb.WriteString("\n---\n")
    }
    sb.WriteString("\n## Implementation Tasks\n")
    for _, task := range ctx.Tasks {
        status := " "
        if task.Completed {
            status = "x"
        }
        sb.WriteString(fmt.Sprintf("- [%s] %s\n", status, task.Description))
    }
    sb.WriteString("\n## Relevant Files\n")
    for _, path := range ctx.RelevantPaths {
        sb.WriteString(fmt.Sprintf("- %s\n", path))
    }
    return sb.String(), nil
}

3.3 CLI‑Befehl für Graph‑Build

Datei: cmd/sin-code/spec_build_cmd.go (Erweiterung)

var specBuildGraphCmd = &cobra.Command{
    Use:   "build‑graph",
    Short: "Build the spec‑graph index",
    RunE: func(cmd *cobra.Command, args []string) error {
        idx := graph.NewIndexer(".")
        g, err := idx.Index()
        if err != nil {
            return err
        }
        
        fmt.Printf("✅ Built spec‑graph: %d nodes, %d edges\n", len(g.Nodes), len(g.Edges))
        return nil
    },
}

var specCompileCmd = &cobra.Command{
    Use:   "compile <change‑id>",
    Short: "Compile deterministic context for a change",
    Args:  cobra.ExactArgs(1),
    RunE: func(cmd *cobra.Command, args []string) error {
        compiler, err := NewCompiler(".")
        if err != nil {
            return err
        }
        
        context, err := compiler.GenerateContextForAgent(args[0])
        if err != nil {
            return err
        }
        
        fmt.Println(context)
        return nil
    },
}

Der SpecD‑Port bringt deterministische Intelligenz in die Spec‑Ebene. Der Agent bekommt exakt die relevanten Specs und Dateien – keine Halluzinationen mehr über Kontext.

4. Phase 3 – Quality Gates & Agentische SDLC‑Pipeline – Integration von SDLC

SDLC bringt agentische Quality Gates in die Pipeline. Jede Phase hat ein automatisiertes Gate:

  • Lint Gate – Code‑Qualität
  • Test Gate – Tests müssen passieren
  • Coverage Gate – Min‑Coverage erzwingen
  • Security Gate – SCA‑Scan
  • Architecture Gate – Design‑Review

4.1 Quality Gate Framework

Datei: internal/pipeline/gate.go

package pipeline

import (
    "bytes"
    "encoding/json"
    "fmt"
    "os"
    "os/exec"
    "strings"
)

// GateResult contains the outcome of a quality gate.
type GateResult struct {
    Name    string   `json:"name"`
    Passed  bool     `json:"passed"`
    Message string   `json:"message"`
    Details []string `json:"details,omitempty"`
}

// Gate defines a quality gate interface.
type Gate interface {
    Name() string
    Run() GateResult
}

// LintGate runs golangci‑lint.
type LintGate struct{}

func (g LintGate) Name() string { return "lint" }

func (g LintGate) Run() GateResult {
    cmd := exec.Command("golangci‑lint", "run", "--out‑format", "json")
    output, err := cmd.CombinedOutput()
    
    if err != nil {
        var issues []map[string]interface{}
        if json.Unmarshal(output, &issues) == nil && len(issues) > 0 {
            details := make([]string, 0, len(issues))
            for _, issue := range issues {
                if loc, ok := issue["location"]; ok {
                    details = append(details, fmt.Sprintf("  %v", loc))
                }
            }
            return GateResult{
                Name:    "lint",
                Passed:  false,
                Message: fmt.Sprintf("Linting failed: %v", err),
                Details: details,
            }
        }
        return GateResult{
            Name:    "lint",
            Passed:  false,
            Message: fmt.Sprintf("Linting failed: %v", err),
        }
    }
    
    return GateResult{
        Name:    "lint",
        Passed:  true,
        Message: "All files passed linting",
    }
}

// TestGate runs go test.
type TestGate struct {
    TestCmd string
}

func (g TestGate) Name() string { return "test" }

func (g TestGate) Run() GateResult {
    cmd := exec.Command("sh", "-c", g.TestCmd)
    var stdout, stderr bytes.Buffer
    cmd.Stdout = &stdout
    cmd.Stderr = &stderr
    
    err := cmd.Run()
    if err != nil {
        return GateResult{
            Name:    "test",
            Passed:  false,
            Message: fmt.Sprintf("Tests failed: %v", err),
            Details: []string{stderr.String()},
        }
    }
    return GateResult{
        Name:    "test",
        Passed:  true,
        Message: "All tests passed",
    }
}

// CoverageGate checks minimum coverage.
type CoverageGate struct {
    MinCoverage float64
}

func (g CoverageGate) Name() string { return "coverage" }

func (g CoverageGate) Run() GateResult {
    // Run tests with coverage
    cmd := exec.Command("go", "test", "./...", "-coverprofile=coverage.out")
    if err := cmd.Run(); err != nil {
        return GateResult{
            Name:    "coverage",
            Passed:  false,
            Message: fmt.Sprintf("Could not run coverage: %v", err),
        }
    }
    defer os.Remove("coverage.out")
    
    // Parse coverage
    cmd = exec.Command("go", "tool", "cover", "-func=coverage.out")
    output, err := cmd.Output()
    if err != nil {
        return GateResult{
            Name:    "coverage",
            Passed:  false,
            Message: fmt.Sprintf("Could not parse coverage: %v", err),
        }
    }
    
    // Extract total coverage percentage
    lines := strings.Split(string(output), "\n")
    for _, line := range lines {
        if strings.Contains(line, "total:") {
            var total float64
            fmt.Sscanf(line, "total: (statements) %f%%", &total)
            if total < g.MinCoverage {
                return GateResult{
                    Name:    "coverage",
                    Passed:  false,
                    Message: fmt.Sprintf("Coverage %.1f%% below minimum %.1f%%", total, g.MinCoverage),
                }
            }
            return GateResult{
                Name:    "coverage",
                Passed:  true,
                Message: fmt.Sprintf("Coverage %.1f%% meets minimum %.1f%%", total, g.MinCoverage),
            }
        }
    }
    
    return GateResult{
        Name:    "coverage",
        Passed:  true,
        Message: "Coverage check passed",
    }
}

4.2 Pipeline Orchestrator

Datei: internal/pipeline/pipeline.go

package pipeline

import (
    "encoding/json"
    "fmt"
    "os"
    "path/filepath"
)

// Pipeline represents an agentic SDLC pipeline.
type Pipeline struct {
    ChangeID string
    Gates    []Gate
}

// NewPipeline creates a pipeline for a change.
func NewPipeline(changeID string) *Pipeline {
    return &Pipeline{
        ChangeID: changeID,
        Gates: []Gate{
            LintGate{},
            TestGate{TestCmd: "go test ./... -count=1"},
            CoverageGate{MinCoverage: 70.0},
        },
    }
}

// Run executes all gates and returns the results.
func (p *Pipeline) Run() ([]GateResult, bool) {
    results := make([]GateResult, 0, len(p.Gates))
    allPassed := true
    
    for _, gate := range p.Gates {
        result := gate.Run()
        results = append(results, result)
        if !result.Passed {
            allPassed = false
            fmt.Printf("❌ Gate '%s' failed: %s\n", gate.Name(), result.Message)
        } else {
            fmt.Printf("✅ Gate '%s' passed\n", gate.Name())
        }
    }
    
    // Persist results
    p.saveResults(results)
    return results, allPassed
}

func (p *Pipeline) saveResults(results []GateResult) {
    resultsPath := filepath.Join("changes", p.ChangeID, "gates.json")
    data, _ := json.MarshalIndent(results, "", "  ")
    os.WriteFile(resultsPath, data, 0644)
}

4.3 Integration in den Agent‑Loop

Die Pipeline wird vor dem Archivieren einer Change ausgeführt – als ultimatives Quality Gate, bevor Specs gemerged werden.

Die SDLC‑Integration bringt professionelle Qualitätskontrollen in jede Change. Keine Änderung wird ohne automatische Verifikation abgeschlossen – perfekt zur SIN‑Code‑Philosophie.

5. Phase 4 – MetaSpec‑Integration – Speckit‑Generator & Token‑Optimierung

MetaSpec ist das Meta‑Framework zur Generierung von Speckits. Es bringt zwei revolutionäre Ideen:

  1. Speckit‑Generierung – Aus einer SDS‑Spezifikation wird ein vollständiges Toolkit generiert (CLI, Parser, Validator, Templates, AI‑Befehle)
  2. Präzisionsgesteuerte Navigation – Token‑Einsparungen von 84–99% durch line‑number‑basiertes Lesen

5.1 Speckit‑Generator (Port nach Go)

Datei: internal/metaspec/generator.go

package metaspec

import (
    "bytes"
    "embed"
    "fmt"
    "os"
    "path/filepath"
    "strings"
    "text/template"
)

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

// Speckit represents a generated specification toolkit.
type Speckit struct {
    Name        string
    Domain      string // development, testing, documentation, operations, custom
    OutputPath  string
    Commands    []Command
    Validators  []Validator
}

type Command struct {
    Name        string
    Description string
    Template    string
}

type Validator struct {
    Rule string
    Script string
}

// Generator creates speckits from SDS specifications.
type Generator struct {
    outputPath string
}

// NewGenerator creates a new speckit generator.
func NewGenerator(outputPath string) *Generator {
    return &Generator{outputPath: outputPath}
}

// Generate creates a complete speckit for a domain.
func (g *Generator) Generate(domain string) error {
    speckit := &Speckit{
        Name:       fmt.Sprintf("%s‑spec‑kit", domain),
        Domain:     domain,
        OutputPath: g.outputPath,
    }
    
    // Create directory structure
    dirs := []string{
        g.outputPath,
        filepath.Join(g.outputPath, "cmd"),
        filepath.Join(g.outputPath, "internal", "parser"),
        filepath.Join(g.outputPath, "internal", "validator"),
        filepath.Join(g.outputPath, "templates"),
        filepath.Join(g.outputPath, "commands"),
    }
    for _, dir := range dirs {
        if err := os.MkdirAll(dir, 0755); err != nil {
            return err
        }
    }
    
    // Generate main.go
    if err := g.generateMain(speckit); err != nil {
        return err
    }
    
    // Generate parser
    if err := g.generateParser(speckit); err != nil {
        return err
    }
    
    // Generate validator
    if err := g.generateValidator(speckit); err != nil {
        return err
    }
    
    // Generate slash commands for AI agents
    if err := g.generateCommands(speckit); err != nil {
        return err
    }
    
    // Generate AGENTS.md with precision navigation
    if err := g.generateAgentsMD(speckit); err != nil {
        return err
    }
    
    fmt.Printf("✅ Generated speckit for domain '%s' at %s\n", domain, g.outputPath)
    return nil
}

func (g *Generator) generateMain(s *Speckit) error {
    tpl := `package main

import (
    "fmt"
    "os"
    
    "{{.Name}}/internal/parser"
    "{{.Name}}/internal/validator"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println("Usage: {{.Name}} <command> [args]")
        fmt.Println("Commands: validate, generate, list")
        os.Exit(1)
    }
    
    switch os.Args[1] {
    case "validate":
        if err := validator.Validate(os.Args[2]); err != nil {
            fmt.Fprintf(os.Stderr, "Validation failed: %v\n", err)
            os.Exit(1)
        }
        fmt.Println("✅ Valid")
    case "generate":
        // Generate from spec
    case "list":
        // List available specs
    default:
        fmt.Printf("Unknown command: %s\n", os.Args[1])
        os.Exit(1)
    }
}
`
    tmpl, err := template.New("main").Parse(tpl)
    if err != nil {
        return err
    }
    
    f, err := os.Create(filepath.Join(g.outputPath, "main.go"))
    if err != nil {
        return err
    }
    defer f.Close()
    
    return tmpl.Execute(f, s)
}

func (g *Generator) generateParser(s *Speckit) error {
    tpl := `package parser

import (
    "bufio"
    "os"
    "strings"
)

// Spec represents a parsed specification.
type Spec struct {
    Title       string
    Requirements []Requirement
}

type Requirement struct {
    Text    string
    Priority string // MUST, SHOULD, MAY
}

// Parse reads and parses a spec file.
func Parse(path string) (*Spec, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()
    
    spec := &Spec{}
    scanner := bufio.NewScanner(file)
    
    for scanner.Scan() {
        line := scanner.Text()
        if strings.HasPrefix(line, "# ") {
            spec.Title = strings.TrimPrefix(line, "# ")
        }
        if strings.Contains(line, "MUST") {
            spec.Requirements = append(spec.Requirements, Requirement{
                Text:     line,
                Priority: "MUST",
            })
        }
        if strings.Contains(line, "SHOULD") {
            spec.Requirements = append(spec.Requirements, Requirement{
                Text:     line,
                Priority: "SHOULD",
            })
        }
    }
    return spec, scanner.Err()
}
`
    tmpl, err := template.New("parser").Parse(tpl)
    if err != nil {
        return err
    }
    
    f, err := os.Create(filepath.Join(g.outputPath, "internal", "parser", "parser.go"))
    if err != nil {
        return err
    }
    defer f.Close()
    
    return tmpl.Execute(f, s)
}

func (g *Generator) generateValidator(s *Speckit) error {
    tpl := `package validator

import (
    "fmt"
    "os"
    "regexp"
)

// Validate checks a spec file for correctness.
func Validate(path string) error {
    content, err := os.ReadFile(path)
    if err != nil {
        return err
    }
    
    // Check for required sections
    required := []string{"## Purpose", "## Requirements"}
    for _, req := range required {
        if !regexp.MustCompile(req).Match(content) {
            return fmt.Errorf("missing required section: %s", req)
        }
    }
    
    // Check requirement format
    reqPattern := regexp.MustCompile(`(?m)^###\s+Requirement:`)
    if !reqPattern.Match(content) {
        return fmt.Errorf("no requirements found (format: '### Requirement: ...')")
    }
    
    return nil
}
`
    tmpl, err := template.New("validator").Parse(tpl)
    if err != nil {
        return err
    }
    
    f, err := os.Create(filepath.Join(g.outputPath, "internal", "validator", "validator.go"))
    if err != nil {
        return err
    }
    defer f.Close()
    
    return tmpl.Execute(f, s)
}

func (g *Generator) generateCommands(s *Speckit) error {
    commands := []string{
        "specify.md.j2",
        "plan.md.j2", 
        "tasks.md.j2",
        "implement.md.j2",
        "validate.md.j2",
    }
    
    for _, cmd := range commands {
        tplContent, err := templateFS.ReadFile(fmt.Sprintf("templates/%s", cmd))
        if err != nil {
            continue
        }
        
        outPath := filepath.Join(g.outputPath, "commands", strings.TrimSuffix(cmd, ".j2"))
        if err := os.WriteFile(outPath, tplContent, 0644); err != nil {
            return err
        }
    }
    return nil
}

func (g *Generator) generateAgentsMD(s *Speckit) error {
    content := fmt.Sprintf(`# AGENTS.md – %s Speckit

## Precision Navigation for AI Agents

This speckit uses **precision‑guided navigation** to minimize token usage.
Each command file includes a Navigation Guide with exact line ranges.

### Available Commands

| Command | Purpose | Lines | Token Savings |
|---------|---------|-------|---------------|
| /specify | Define specifications | 30‑350 | 95% |
| /plan | Create implementation plan | 50‑420 | 93% |
| /tasks | Break down into tasks | 40‑280 | 97% |
| /implement | Generate code from specs | 100‑850 | 84% |
| /validate | Validate spec compliance | 60‑400 | 90% |

### How to Use

Instead of loading entire command files, read only the sections you need:

read_file("commands/specify.md", offset=200, limit=50)  # Only the validation section

For Python‑specific implementation steps (97% token savings):
read_file("commands/implement.md", offset=210, limit=25)

### Navigation Guides

Each command file begins with a table of line ranges. Use read_file() with offset/limit to fetch exactly what your agent needs.
`, s.Name)
    
    return os.WriteFile(filepath.Join(g.outputPath, "AGENTS.md"), []byte(content), 0644)
}

5.2 Präzisionsgesteuerte Navigation in SIN‑Code

Datei: internal/metaspec/navigation.go

package metaspec

import (
    "fmt"
    "os"
    "strconv"
    "strings"
)

// NavigationGuide maps section names to line ranges.
type NavigationGuide struct {
    Sections map[string]LineRange
}

type LineRange struct {
    Start int
    End   int
}

// ParseNavigationGuide extracts line ranges from a command file's header.
func ParseNavigationGuide(content string) *NavigationGuide {
    guide := &NavigationGuide{
        Sections: make(map[string]LineRange),
    }
    
    lines := strings.Split(content, "\n")
    inTable := false
    
    for i, line := range lines {
        if strings.Contains(line, "Navigation Guide") || strings.Contains(line, "| Section | Lines |") {
            inTable = true
            continue
        }
        if inTable && strings.HasPrefix(line, "|") && strings.Contains(line, "|") {
            parts := strings.Split(line, "|")
            if len(parts) >= 4 {
                section := strings.TrimSpace(parts[1])
                rangeStr := strings.TrimSpace(parts[2])
                if strings.Contains(rangeStr, "-") {
                    bounds := strings.Split(rangeStr, "-")
                    start, _ := strconv.Atoi(bounds[0])
                    end, _ := strconv.Atoi(bounds[1])
                    guide.Sections[section] = LineRange{Start: start, End: end}
                }
            }
        }
        if inTable && strings.HasPrefix(line, "```") {
            break
        }
    }
    return guide
}

// ReadPrecisionSlice reads only the specified line range from a file.
func ReadPrecisionSlice(path string, start, end int) (string, error) {
    content, err := os.ReadFile(path)
    if err != nil {
        return "", err
    }
    
    lines := strings.Split(string(content), "\n")
    if start < 1 {
        start = 1
    }
    if end > len(lines) {
        end = len(lines)
    }
    if start > end {
        return "", fmt.Errorf("invalid range: %d‑%d", start, end)
    }
    
    return strings.Join(lines[start1:end], "\n"), nil
}

Die MetaSpec‑Integration ermöglicht das Generieren von domain‑spezifischen Speckits direkt aus SIN‑Code heraus – und reduziert Token‑Kosten drastisch.

6. Phase 5 – Spec‑Kit‑Stil Slash‑Commands & Speckit‑UI

SpecKit hat das erfolgreichste Slash‑Command‑Interface. Wir übernehmen dieses Muster für SIN‑Code.

6.1 Slash‑Command Integration

Datei: cmd/sin-code/slash_cmds.go

package main

// SlashCommand represents a slash command for TUI/WebUI.
type SlashCommand struct {
    Name        string
    Description string
    Handler     func(args string) (string, error)
}

var slashCommands = []SlashCommand{
    {
        Name:        "/specify",
        Description: "Create or update a specification",
        Handler: func(args string) (string, error) {
            // Create a new change with spec
            cmd := exec.Command("sin‑code", "spec", "change", "create", args)
            output, err := cmd.CombinedOutput()
            return string(output), err
        },
    },
    {
        Name:        "/plan",
        Description: "Generate implementation plan from spec",
        Handler: func(args string) (string, error) {
            // Parse spec and generate plan
            return generatePlan(args), nil
        },
    },
    {
        Name:        "/tasks",
        Description: "Break down plan into tasks",
        Handler: func(args string) (string, error) {
            return generateTasks(args), nil
        },
    },
    {
        Name:        "/implement",
        Description: "Implement tasks with verification",
        Handler: func(args string) (string, error) {
            // Run agent on the change
            cmd := exec.Command("sin‑code", "chat", "-p", 
                fmt.Sprintf("Implement change %s with verification", args))
            output, err := cmd.CombinedOutput()
            return string(output), err
        },
    },
    {
        Name:        "/validate",
        Description: "Validate spec compliance",
        Handler: func(args string) (string, error) {
            cmd := exec.Command("sin‑code", "spec", "validate", args)
            output, err := cmd.CombinedOutput()
            return string(output), err
        },
    },
    {
        Name:        "/archive",
        Description: "Archive completed change",
        Handler: func(args string) (string, error) {
            // Run quality gates first
            pipeline := pipeline.NewPipeline(args)
            results, allPassed := pipeline.Run()
            
            if !allPassed {
                return fmt.Sprintf("Cannot archive: quality gates failed\n%v", results), nil
            }
            
            cmd := exec.Command("sin‑code", "spec", "change", "archive", args)
            output, err := cmd.CombinedOutput()
            return string(output), err
        },
    },
}

6.2 TUI‑Integration

Die bestehenden TUI‑Kommandos (sin-code chat) werden um Slash‑Command‑Erkennung erweitert:

// In chat_cmd.go, in the REPL loop:
func handleSlashCommand(input string) (string, error) {
    if !strings.HasPrefix(input, "/") {
        return "", nil
    }
    
    parts := strings.Fields(input)
    if len(parts) == 0 {
        return "", nil
    }
    
    cmdName := parts[0]
    args := strings.Join(parts[1:], " ")
    
    for _, sc := range slashCommands {
        if sc.Name == cmdName {
            return sc.Handler(args)
        }
    }
    return "", fmt.Errorf("unknown command: %s", cmdName)
}

Die Spec‑Kit‑Integration macht SIN‑Code zu einem Citizen‑Agent in jedem SDD‑Workflow – keine Tool‑Brüche mehr für die Nutzer.

7. Gesamtarchitektur & Einbettung in SIN‑Code

Die neue Spec‑Layer passt sich nahtlos in SIN‑Codes bestehende Paketstruktur ein:

Vollständige Paketstruktur nach Integration

SIN-Code/
├── cmd/sin-code/
│   ├── main.go
│   ├── chat_cmd.go              # Erweitert: Slash‑Commands
│   ├── spec_cmd.go              # NEU: spec init, validate, change create/archive
│   ├── spec_build_cmd.go        # NEU: build‑graph, compile
│   ├── speckit_cmd.go           # NEU: metaspec generate
│   ├── pipeline_cmd.go          # NEU: pipeline run, status
│   └── ...
│
├── internal/
│   ├── spec/                    # NEU: Spec‑Backbone (Phase 1)
│   │   ├── types.go
│   │   ├── validate.go
│   │   └── merge.go
│   │
│   ├── spec/graph/              # NEU: Code‑Graph (Phase 2)
│   │   ├── indexer.go
│   │   └── graph.go
│   │
│   ├── spec/compiler.go         # NEU: Deterministischer Compiler
│   │
│   ├── pipeline/                # NEU: Quality Gates (Phase 3)
│   │   ├── gate.go
│   │   └── pipeline.go
│   │
│   ├── metaspec/                # NEU: Speckit‑Generator (Phase 4)
│   │   ├── generator.go
│   │   ├── navigation.go
│   │   └── templates/           # Embedded templates
│   │
│   ├── agentloop/               # BESTEHEND: Erweitert um Spec‑Context
│   │   ├── loop.go              # MODIFIED: Injects compiled context
│   │   └── ...
│   │
│   ├── verify/                  # BESTEHEND: Bleibt das Verifikations‑Gate
│   │   └── ...
│   │
│   └── ... (bestehende Pakete)
│
├── AGENTS.md                    # BESTEHEND: Wird um Spec‑Befehle erweitert
├── docs/SPEC.md                 # NEU: Vollständige Spec‑Dokumentation
└── ...

WebUI‑Integration

Die WebUI wird um ein Spec‑Dashboard erweitert:

// In webui/src/components/SpecDashboard.tsx
export function SpecDashboard() {
    const [changes, setChanges] = useState([]);
    const [specGraph, setSpecGraph] = useState(null);
    
    useEffect(() => {
        fetch('/api/spec/changes').then(res => res.json()).then(setChanges);
        fetch('/api/spec/graph').then(res => res.json()).then(setSpecGraph);
    }, []);
    
    return (
        <div>
            <h2>Active Changes</h2>
            {changes.map(change => (
                <ChangeCard key={change.id} change={change} />
            ))}
            <h2>Spec Graph</h2>
            <GraphVisualization graph={specGraph} />
        </div>
    );
}

8. Rollout‑Plan & Abschlussbemerkung

Migrationspfad

Phase Dauer Deliverable Erfolgskriterium
Phase 1 (Spectr) 1 Woche spec init, spec validate, spec change create/archive CRUD auf Changes + deterministisches Merging
Phase 2 (SpecD) 1 Woche spec build‑graph, spec compile Code‑Graph + deterministischer Context
Phase 3 (SDLC) 3 Tage pipeline run, Quality Gates Automatische Tests/Coverage/Lint vor Archivierung
Phase 4 (MetaSpec) 3 Tage speckit generate, Navigation Guides Generierung funktionaler Speckits
Phase 5 (SpecKit) 2 Tage Slash‑Commands, WebUI‑Dashboard /specify, /plan, /tasks, /implement
Integration & Tests 3 Tage Vollständige E2E‑Tests 100% Pass‑Rate

Die grosse Chance

Mit dieser Fusion wird SIN‑Code zum ersten Coding‑Agenten, der gleichzeitig:

  • Verification‑First arbeitet (bestehend)
  • Spec‑First plant (neu)
  • Deterministisch spezifische Änderungen merged
  • Code‑Graph‑basierten Kontext liefert
  • Automatische Quality Gates durchsetzt
  • Speckits für jede Domäne generieren kann
  • Token‑Effizienz von 84‑99% erreicht

"Specifications become executable, directly generating working implementations rather than just guiding them." – Spec Kit

SIN‑Code ist die perfekte Plattform, um diese Vision als erster Go‑basierter Agent zu realisieren. Die Community von OpenSpec (34.5k Stars), SpecKit (82.5k Stars) und Superpowers (115k Stars) zeigt: SDD ist der klare Trend. SIN‑Code kann diesen Trend mit seiner einzigartigen Architektur dominieren.

Die nächsten Schritte:

# 1. Phase 1 – Spectr‑Backbone implementieren
git checkout -b feature/spec-backbone
# ... Code aus Abschnitt 2 einfügen

# 2. Phase 2 – SpecD‑Compiler hinzufügen
git checkout -b feature/spec-compiler
# ... Code aus Abschnitt 3 einfügen

# 3. Alle Phasen zusammenführen und testen
sin spec init
sin spec change create "add-rate-limiting"
sin spec compile add-rate-limiting
sin pipeline run add-rate-limiting
sin spec change archive add-rate-limiting

Sie haben bereits eines der fortschrittlichsten AI‑Coding‑Frameworks. Mit dieser Spezifikations‑Schicht wird SIN‑Code das massgeblichste Werkzeug seiner Klasse. 🚀

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions