Architecture Data Flow - aku11i/phantom GitHub Wiki

Data Flow

This document illustrates how data moves through Phantom's system, from user input to final output.

Overview

Data flows through Phantom in a predictable, unidirectional manner:

graph LR
    A[User Input] --> B[CLI Parser]
    B --> C[Command Handler]
    C --> D[Core Logic]
    D --> E[Git Operations]
    E --> F[System Calls]
    F --> G[Results]
    G --> H[Output Formatting]
    H --> I[User Output]
    
    style A fill:#9f9
    style I fill:#9f9
    style D fill:#ff9
    style E fill:#f9f
Loading

Command Execution Flow

1. Create Command Flow

Example: phantom create feature-xyz origin/main

sequenceDiagram
    participant User
    participant CLI
    participant CreateHandler
    participant WorktreeCore
    participant GitModule
    participant FileSystem
    
    User->>CLI: phantom create feature-xyz origin/main
    
    CLI->>CreateHandler: {name: "feature-xyz", branch: "origin/main"}
    
    CreateHandler->>WorktreeCore: validateWorktreeName("feature-xyz")
    WorktreeCore-->>CreateHandler: Result.ok()
    
    CreateHandler->>GitModule: getGitRoot()
    GitModule->>FileSystem: git rev-parse --show-toplevel
    FileSystem-->>GitModule: "/path/to/repo"
    GitModule-->>CreateHandler: Result.ok("/path/to/repo")
    
    CreateHandler->>GitModule: branchExists("origin/main")
    GitModule->>FileSystem: git rev-parse --verify
    FileSystem-->>GitModule: "commit-sha"
    GitModule-->>CreateHandler: Result.ok(true)
    
    CreateHandler->>WorktreeCore: createWorktree("feature-xyz", "origin/main")
    
    WorktreeCore->>GitModule: addWorktree(name, branch, path)
    GitModule->>FileSystem: git worktree add
    FileSystem-->>GitModule: success
    
    GitModule-->>WorktreeCore: Result.ok(WorktreeInfo)
    WorktreeCore-->>CreateHandler: Result.ok(WorktreeInfo)
    
    CreateHandler->>CLI: formatSuccess(WorktreeInfo)
    CLI->>User: "Created phantom 'feature-xyz' at /tmp/phantom/repo/feature-xyz"
Loading

2. List Command Flow

Example: phantom list

sequenceDiagram
    participant User
    participant CLI
    participant ListHandler
    participant WorktreeCore
    participant GitModule
    participant OutputFormatter
    
    User->>CLI: phantom list
    
    CLI->>ListHandler: {}
    
    ListHandler->>WorktreeCore: listWorktrees()
    
    WorktreeCore->>GitModule: listWorktrees()
    GitModule->>GitModule: git worktree list --porcelain
    GitModule-->>WorktreeCore: Result.ok(GitWorktreeData[])
    
    WorktreeCore->>WorktreeCore: Transform to WorktreeInfo[]
    WorktreeCore-->>ListHandler: Result.ok(WorktreeInfo[])
    
    ListHandler->>OutputFormatter: formatTable(worktrees)
    OutputFormatter-->>ListHandler: Formatted table string
    
    ListHandler->>CLI: Output table
    CLI->>User: Display formatted table
Loading

Data Transformation Pipeline

1. Input Processing

graph TB
    A[Raw CLI Args] --> B[Parsed Arguments]
    B --> C[Validated Input]
    C --> D[Domain Objects]
    
    subgraph "CLI Layer"
        A
        B
    end
    
    subgraph "Handler Layer"
        C
    end
    
    subgraph "Core Layer"
        D
    end
Loading

Example Transformations:

// Raw input
["create", "my-feature", "origin/main"]

// Parsed arguments
{
  command: "create",
  args: ["my-feature", "origin/main"],
  flags: {}
}

// Validated input
{
  name: "my-feature",
  branch: "origin/main"
}

// Domain object
{
  name: "my-feature",
  branch: "origin/main",
  path: "/tmp/phantom/repo/my-feature"
}

2. Git Data Processing

graph LR
    A[Git CLI Output] --> B[Raw String]
    B --> C[Parsed Data]
    C --> D[Domain Model]
    D --> E[Result Type]
    
    style A fill:#f9f
    style E fill:#9f9
Loading

Example: Worktree List Parsing

// Git output (porcelain format)
`worktree /path/to/main
HEAD abc123
branch refs/heads/main

worktree /tmp/phantom/repo/feature
HEAD def456
branch refs/heads/feature`

// Parsed data
[
  {
    path: "/path/to/main",
    head: "abc123",
    branch: "refs/heads/main"
  },
  {
    path: "/tmp/phantom/repo/feature",
    head: "def456", 
    branch: "refs/heads/feature"
  }
]

// Domain model
[
  {
    name: "main",
    path: "/path/to/main",
    branch: "main",
    isMain: true
  },
  {
    name: "feature",
    path: "/tmp/phantom/repo/feature",
    branch: "feature",
    isMain: false
  }
]

Error Flow

Error Propagation

graph TB
    A[System Error] --> B[Git Error]
    B --> C[Domain Error]
    C --> D[User Error]
    
    subgraph "Infrastructure"
        A
    end
    
    subgraph "Git Module"
        B
    end
    
    subgraph "Core Module"
        C
    end
    
    subgraph "CLI Layer"
        D
    end
    
    style A fill:#f99
    style D fill:#fcc
Loading

Error Transformation Example:

// System error
Error: Command failed: git worktree add
fatal: 'feature' is already checked out

// Git module error
GitError: Worktree 'feature' already exists

// Domain error  
WorktreeError: A phantom named 'feature' already exists

// User message
Error: A phantom named 'feature' already exists.
Try a different name or delete the existing phantom first.

Result Type Flow

sequenceDiagram
    participant Git
    participant Core
    participant Handler
    participant User
    
    Git->>Git: Execute command
    
    alt Success
        Git->>Core: Result.ok(data)
        Core->>Core: Transform data
        Core->>Handler: Result.ok(domainObject)
        Handler->>User: Success message
    else Failure
        Git->>Core: Result.error(gitError)
        Core->>Core: Map to domain error
        Core->>Handler: Result.error(domainError)
        Handler->>User: Error message + help
    end
Loading

State Flow

Worktree State Management

stateDiagram-v2
    [*] --> NonExistent
    NonExistent --> Creating: create command
    Creating --> Active: git worktree add
    Active --> Deleting: delete command
    Deleting --> NonExistent: git worktree remove
    
    Active --> Active: exec/shell commands
    
    Creating --> NonExistent: error
    Deleting --> Active: error
Loading

Process State Flow

graph LR
    A[Idle] --> B[Spawning]
    B --> C[Running]
    C --> D[Completed]
    C --> E[Failed]
    
    D --> F[Exit Code 0]
    E --> G[Exit Code > 0]
    
    style A fill:#ccc
    style C fill:#9f9
    style D fill:#9f9
    style E fill:#f99
Loading

Async Data Flow

Command Execution Pipeline

sequenceDiagram
    participant Handler
    participant Process
    participant Shell
    participant Output
    
    Handler->>Process: exec(command)
    
    Process->>Shell: spawn(command)
    activate Shell
    
    loop Output Stream
        Shell-->>Process: stdout data
        Process-->>Handler: stream chunk
        Handler-->>Output: display chunk
    end
    
    Shell-->>Process: exit(code)
    deactivate Shell
    
    Process-->>Handler: Result<ExitCode>
    Handler-->>Output: final status
Loading

Data Validation Flow

Input Validation Pipeline

graph TB
    A[User Input] --> B{Valid Format?}
    B -->|No| C[Format Error]
    B -->|Yes| D{Valid Characters?}
    D -->|No| E[Character Error]
    D -->|Yes| F{Name Available?}
    F -->|No| G[Conflict Error]
    F -->|Yes| H[Proceed]
    
    C --> I[Error Message]
    E --> I
    G --> I
    
    style B fill:#ff9
    style D fill:#ff9
    style F fill:#ff9
    style I fill:#f99
    style H fill:#9f9
Loading

Validation Stages:

  1. Format Validation

    • Non-empty name
    • No path separators
    • No special characters
  2. Character Validation

    • Alphanumeric and hyphens only
    • No spaces or dots
    • No path traversal
  3. Availability Check

    • Name not already used
    • No conflicts with existing

Output Formatting Flow

Table Rendering Pipeline

graph LR
    A[Domain Objects] --> B[Extract Fields]
    B --> C[Calculate Widths]
    C --> D[Format Rows]
    D --> E[Add Headers]
    E --> F[Render Table]
    
    subgraph "Data Preparation"
        A
        B
    end
    
    subgraph "Layout Calculation"
        C
    end
    
    subgraph "Rendering"
        D
        E
        F
    end
Loading

Example: List Output

// Domain objects
[
  { name: "main", branch: "main", path: "/repo" },
  { name: "feature", branch: "feature/new", path: "/tmp/phantom/repo/feature" }
]

// Extracted fields
[
  ["main", "main", "/repo"],
  ["feature", "feature/new", "/tmp/phantom/repo/feature"]
]

// Calculated widths
{ name: 7, branch: 11, path: 25 }

// Formatted output
NAME     BRANCH       PATH
main     main         /repo
feature  feature/new  /tmp/phantom/repo/feature

Performance Considerations

Data Flow Optimization

graph TB
    A[Minimize Transformations] --> B[Stream When Possible]
    B --> C[Cache Expensive Operations]
    C --> D[Fail Fast]
    
    E[Git Calls] --> F[Batch Operations]
    F --> G[Use Porcelain Format]
    
    H[Output] --> I[Progressive Rendering]
    I --> J[Lazy Evaluation]
Loading

Optimization Strategies:

  1. Stream Processing

    • Don't buffer entire output
    • Process line by line
    • Immediate user feedback
  2. Efficient Git Usage

    • Use --porcelain for parsing
    • Combine operations when possible
    • Cache repository information
  3. Fast Failure

    • Validate early
    • Check prerequisites first
    • Avoid unnecessary work

Data Flow Patterns

1. Command Pattern

interface Command {
  validate(input: Input): Result<ValidatedInput>
  execute(input: ValidatedInput): Result<Output>
  format(output: Output): string
}

2. Pipeline Pattern

const pipeline = 
  parseArgs
  .andThen(validate)
  .andThen(execute)
  .andThen(format)
  .mapError(handleError)

3. Stream Pattern

spawn(command)
  .stdout
  .pipe(lineParser)
  .pipe(transformer)
  .pipe(output)

Summary

Phantom's data flow architecture ensures:

  1. Predictability: Data flows in one direction
  2. Traceability: Clear transformation points
  3. Type Safety: Strongly typed at boundaries
  4. Error Handling: Explicit error propagation
  5. Performance: Efficient data processing

The unidirectional flow and clear transformation boundaries make the system easy to understand, debug, and extend.

⚠️ **GitHub.com Fallback** ⚠️