packages feed

clod-0.1.0: PROJECT_ARCHITECTURE.md

# Clod Project Architecture

This document outlines the architecture, components, and design decisions for the Clod project.

## Project Overview

Clod (Claude Optimization Driver) is a tool designed to prepare text files for optimal processing by Claude AI models. It helps:

- Transform text files to be more Claude-friendly
- Generate manifest files for mapping between original and transformed paths
- Create staging directories with optimized files
- Skip binary files automatically
- Respect ignore patterns (.gitignore, .clodignore)
- Detect file changes efficiently

## Key Components

### Module Structure

- `Clod.Types`: Core data types and type classes
- `Clod.Core`: Main application logic
- `Clod.FileSystem`: File system operations
  - `Clod.FileSystem.Checksums`: Checksum-based file tracking
  - `Clod.FileSystem.Detection`: File type detection
  - `Clod.FileSystem.Operations`: File operations
  - `Clod.FileSystem.Processing`: File processing
  - `Clod.FileSystem.Transformations`: Text transformations
- `Clod.Output`: Output formatting and display
- `Clod.IgnorePatterns`: Pattern matching for ignored files
- `Clod.Capability`: Capability-based security
- `Clod.Config`: Configuration management

## Checksum-Based File Tracking

Clod uses a checksum-based approach for tracking file changes:

- Checksums detect file content changes regardless of modification time
- Works in any directory structure without requiring a Git repository
- Detects file renames by matching identical content with different paths
- Provides a consistent experience across different environments

```haskell
-- Calculate SHA-256 checksum of a ByteString
calculateChecksum :: BS.ByteString -> Checksum
calculateChecksum content =
  let hash = SHA256.hash content
      hexHash = Base16.encode hash
  in Checksum (show hexHash)
```

## Database Structure

The database structure enables efficient queries:

- `dbFiles` maps file paths to their entries for quick lookup by path
- `dbChecksums` maps checksums to paths for detecting renamed files
- `dbLastStagingDir` stores the previous staging directory for the `--last` flag
- Entries contain the full file metadata including content hash, modification time, and optimized name

```haskell
data ClodDatabase = ClodDatabase
  { dbFiles :: !(Map.Map FilePath FileEntry)
  , dbChecksums :: !(Map.Map String FilePath)
  , dbLastStagingDir :: !(Maybe FilePath)
  , dbLastRunTime :: !UTCTime
  } deriving stock (Show, Eq)
```

## Command-Line Interface

Clod provides several command-line options:

- `--verbose`: Enable verbose output
- `--staging`: Specify a custom staging directory
- `--flush`: Flush stale entries from the database
- `--last`: Use the previous staging directory
- `--all-files`: Process all files, not just new or modified ones
- `--modified`: Process only modified files
- `--quiet`: Suppress non-essential output
- `--version`: Show version information
- `--help`: Show help text

## File Change Detection

Clod identifies the following file statuses:

1. `New`: Files not previously in the database
2. `Modified`: Files with a different checksum than the database entry
3. `Unchanged`: Files with the same checksum as the database entry
4. `Deleted`: Files that were in the database but don't exist anymore
5. `Renamed`: Files with an identical checksum but different path

```haskell
detectFileChanges :: FileReadCap -> ClodDatabase -> [FilePath] -> FilePath -> ClodM ([(FilePath, FileStatus)], [(FilePath, FilePath)])
detectFileChanges readCap db filePaths projectRoot = do
  -- For each file, calculate checksum and get modification time
  fileInfos <- catMaybes <$> forM filePaths (\path -> do
      -- Check if file exists and is text, then calculate checksum
      -- ...
    )
  
  -- Detect file statuses
  changedFiles <- findChangedFiles db fileInfos
  
  -- Find renamed files
  let renamedFiles = findRenamedFiles db changedFiles
  
  return (changedFiles, renamedFiles)
```

## Binary File Detection

Clod employs the `magic` library for reliable binary file detection:

1. Uses the same detection mechanism as the Unix `file` command
2. Identifies files by examining their content signatures
3. Provides accurate MIME type classification
4. Works consistently across different platforms

```haskell
-- Check if a file is a text file using libmagic
safeIsTextFile :: FileReadCap -> FilePath -> ClodM Bool
safeIsTextFile readCap path = do
  -- Verify file is within allowed directories first
  allowed <- liftIO $ isPathAllowed (allowedReadDirs readCap) path
  if not allowed
    then throwError $ CapabilityError $ 
      "Access denied: Cannot read file outside allowed directories: " ++ path
    else do
      -- Get the MIME type from the magic library
      mimeType <- liftIO $ getMimeType path
      -- Check if it's a text MIME type
      return $ isMimeTypeText mimeType
```

## Capability-Based Security

Clod implements capability-based security for file operations:

- `FileReadCap`: Grants permission to read from specific directories
- `FileWriteCap`: Grants permission to write to specific directories
- `FileTransformCap`: Grants permission to transform file contents

Each capability checks paths against allowed directories before performing operations.

## Manifest Generation

Clod generates manifest files that map transformed file paths to their original locations:

```json
{
  "transformed/file.txt": "/original/path/to/file.txt",
  "transformed/another-file.txt": "/original/path/to/another-file.txt"
}
```

The manifest helps reconstruct file origins after processing.

## Staging Directory Management

Clod creates staging directories with the following structure:

```
staging-dir/
├── file1.txt
├── file2.txt
├── _path_manifest.dhall
└── ...
```

The `--last` flag functionality allows using the previous staging directory:

```haskell
-- Part of the mainLogic function
when lastMode $ do
  case dbLastStagingDir database of
    Just prevStaging -> do
      when verbose $ liftIO $ hPutStrLn stderr $ 
        "Using previous staging directory: " ++ prevStaging
      -- Output the previous staging directory and exit
      liftIO $ hPutStrLn stdout prevStaging
      throwError $ ConfigError "Using last staging directory as requested"
        
    Nothing -> do
      when verbose $ liftIO $ hPutStrLn stderr 
        "No previous staging directory available, proceeding with new staging"
```

## Error Handling

Clod uses a monad transformer stack for comprehensive error handling:

```haskell
-- Type for the Clod monad
type ClodM a = ExceptT ClodError IO a

-- Error types
data ClodError
  = FileSystemError FilePath IOError
  | ChecksumError String
  | DatabaseError String
  | ConfigError String
  | CapabilityError String
  | IgnorePatternError String
  deriving (Show, Eq)

-- Running the Clod monad
runClodM :: ClodM a -> IO (Either ClodError a)
runClodM = runExceptT
```

## Ignore Pattern Handling

Clod processes ignore patterns similar to .gitignore:

```haskell
-- Parse ignore patterns from file
parseIgnorePatterns :: FilePath -> ClodM [IgnorePattern]
parseIgnorePatterns path = do
  exists <- liftIO $ doesFileExist path
  if not exists
    then return []
    else do
      content <- liftIO $ readFile path
      return $ map IgnorePattern $ parseLines content
  where
    parseLines = filter (not . ignoreLine) . lines
    ignoreLine line = null line || "#" `isPrefixOf` line

-- Check if a file matches ignore patterns
matchesIgnorePattern :: [IgnorePattern] -> FilePath -> Bool
matchesIgnorePattern patterns path =
  any (\(IgnorePattern pattern) -> pathMatchesPattern pattern path) patterns
```

## File Processing Pipeline

The main file processing pipeline consists of several steps:

1. **File Discovery**: Find all files in the project directory
2. **Change Detection**: Identify new, modified, and unchanged files
3. **Filtering**: Apply ignore patterns to exclude files
4. **Text Detection**: Skip binary files
5. **Transformation**: Apply transformations to text files
6. **Staging**: Copy transformed files to the staging directory
7. **Manifest Generation**: Create a mapping between original and transformed paths
8. **Database Update**: Store file metadata for future runs

```haskell
-- Main processing logic
processFiles :: FileReadCap -> FileWriteCap -> FileTransformCap -> [FilePath] -> ClodM ProcessingStats
processFiles readCap writeCap transformCap filePaths = do
  stats <- foldM processOneFile initialStats filePaths
  return stats
  where
    processOneFile stats path = do
      result <- processSingleFile readCap writeCap transformCap path
      return $ updateStats stats result
```

## Path Transformation

Clod transforms file paths to make them more Claude-friendly:

```haskell
-- Transform a file path for Claude
transformFilePath :: FilePath -> OptimizedName
transformFilePath path =
  let parts = splitDirectories path
      transformedParts = map transformPathPart parts
      result = intercalate "/" transformedParts
  in OptimizedName result

-- Transform individual path components
transformPathPart :: String -> String
transformPathPart part
  | null part = ""
  | head part == '.' = "dot--" ++ tail part  -- Handle hidden files/dirs
  | otherwise = part
```

## Future Development

Potential areas for future enhancement:

1. Parallelized file processing for improved performance on large codebases
2. More sophisticated file transformations based on file type
3. Integration with cloud storage services
4. Remote file processing capabilities
5. GUI interface for easier configuration

## Development Guidelines

1. Follow capability-based security principles for all file operations
2. Use pure functions whenever possible
3. Handle errors with proper error types and messages
4. Ensure comprehensive test coverage for all components
5. Maintain backward compatibility with existing configurations