cambria

Cambria Implementation Guide for AI Agents
Login

Last Updated: 2025-12-14

This document provides structured guidance for AI agents implementing and extending the Cambria version control system in Go. It reflects the project's current state, including the completed VFILE system.

Project Status

The foundational library packages (hash, store, artifact) are complete and tested. A major refactoring introduced a transactional database layer and a high-level Repository API. All core VCS operations including Checkin, Checkout, Add, Commit, Diff, and working directory management are now implemented and tested. The VFILE system provides efficient working directory state tracking using SQLite tables (vfile and vmerge). A fully functional CLI with commands for init, add, commit, status, checkout, and diff has been implemented using the urfave/cli v3 framework.

Key Design Principles & Patterns

  1. Minimal and Correct: Simplest correct implementation first.
  2. SQLite-Backed: A single file (*.db) is the source of truth.
  3. Content-Addressable: All artifacts are identified by their SHA-256 hash (UUID).
  4. Immutable Artifacts: Once written, a blob never changes.
  5. Transactional Store Layer: All database operations that modify state must occur within a transaction. The store.DBTX interface abstracts *sql.DB and *sql.Tx to enforce this.
  6. Repository Pattern: All high-level VCS operations are exposed via the vcs.Repository struct, which encapsulates the database connection.
  7. Go Idioms: Standard library first, minimal external dependencies.
  8. Standard Testing: Use only the testing package.

Core Architecture

vcs.Repository

This is the primary entry point for all version control logic. Always use this struct to interact with a repository.

// pkg/vcs/repo.go
type Repository struct {
    db *store.DB
}

// How to use:
repo, err := vcs.InitRepository("path/to/my-repo.db")
// or
repo, err := vcs.OpenRepository("path/to/my-repo.db")

// Perform operations:
uuid, err := repo.Checkin(...)
err = repo.Checkout(...)

store.DBTX Interface

To ensure transactional integrity, all functions in the pkg/store package accept a DBTX interface. This can be either a *store.DB (for single read operations) or a *sql.Tx (for multi-step write operations).

// pkg/store/dbtx.go
type DBTX interface {
    Exec(query string, args ...interface{}) (sql.Result, error)
    Query(query string, args ...interface{}) (*sql.Rows, error)
    QueryRow(query string, args ...interface{}) *sql.Row
}

// Transactional write pattern:
tx, err := repo.DB().Begin()
if err != nil { /* ... */ }
defer tx.Rollback() // Safety net

// ... call store functions with tx ...
err = store.CreateManifest(tx, rid, false)
// ...

return tx.Commit()

Package Structure (Current)

cambria/
├── pkg/
│   ├── hash/           # Content hashing (SHA-256)
│   ├── store/          # SQLite data access layer (uses DBTX)
│   │   ├── db.go
│   │   ├── dbtx.go     # The transactional interface
│   │   ├── schema.go   # Includes vfile and vmerge tables
│   │   ├── blob.go
│   │   ├── manifest.go
│   │   ├── mlink.go
│   │   ├── plink.go
│   │   └── label.go
│   ├── artifact/       # Manifest parsing/generation
│   │   └── manifest.go
│   └── vcs/            # High-level version control operations
│       ├── repo.go                # Repository struct and lifecycle
│       ├── checkin.go             # Commit operation (uses vfile)
│       ├── checkout.go            # Checkout operation (populates vfile)
│       ├── add.go                 # File addition (updates vfile)
│       ├── diff.go                # Diff computation between versions
│       ├── workdir.go             # Working directory state tracking (uses vfile)
│       ├── vfile.go               # VFILE system implementation
│       ├── vfile_test.go          # VFILE unit tests
│       ├── vfile_integration_test.go  # VFILE integration tests
│       ├── checkout_test.go
│       └── main_test.go           # VCS integration tests
├── internal/
│   └── testutil/       # Test helpers
├── cmd/
│   └── cambria/        # CLI application (skeleton exists)
│       ├── main.go
│       ├── init.go
│       ├── add.go
│       ├── commit.go
│       └── checkout.go
└── doc_cambria/        # Design documentation
    ├── CAMBRIA_CLI_PLAN.md      # Phase 2 implementation plan (NEXT)
    ├── CAMBRIA_VFILE_IMPL.md    # VFILE implementation details
    └── ...

Core Data Model (Idempotent Schema)

The schema uses CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS to be safely re-initializable.

-- Immutable artifact storage
CREATE TABLE IF NOT EXISTS blob(
    rid INTEGER PRIMARY KEY AUTOINCREMENT,
    uuid TEXT UNIQUE NOT NULL,
    size INTEGER NOT NULL,
    content BLOB NOT NULL
);

-- Manifest identification
CREATE TABLE IF NOT EXISTS manifest(
    rid INTEGER PRIMARY KEY REFERENCES blob(rid),
    is_merge BOOLEAN DEFAULT 0
);

-- Manifest-file linkage
CREATE TABLE IF NOT EXISTS mlink(
    manifest INTEGER NOT NULL REFERENCES manifest(rid),
    fn TEXT NOT NULL,
    fid INTEGER NOT NULL REFERENCES blob(rid),
    PRIMARY KEY(manifest, fn)
);

-- Parent-child DAG
CREATE TABLE IF NOT EXISTS plink(
    parent INTEGER NOT NULL REFERENCES manifest(rid),
    child INTEGER NOT NULL REFERENCES manifest(rid),
    PRIMARY KEY(parent, child)
);

-- Labels (branches/tags)
CREATE TABLE IF NOT EXISTS label(
    manifest INTEGER NOT NULL REFERENCES manifest(rid),
    name TEXT NOT NULL,
    PRIMARY KEY(manifest, name)
);

-- Configuration
CREATE TABLE IF NOT EXISTS config(
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL
);

-- Working directory file state tracking (VFILE)
CREATE TABLE IF NOT EXISTS vfile(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    vid INTEGER NOT NULL REFERENCES manifest(rid),
    rid INTEGER REFERENCES blob(rid),
    mrid INTEGER REFERENCES blob(rid),
    pathname TEXT NOT NULL COLLATE NOCASE,
    origname TEXT COLLATE NOCASE,
    is_exe BOOLEAN NOT NULL DEFAULT 0,
    is_link BOOLEAN NOT NULL DEFAULT 0,
    chnged INTEGER NOT NULL DEFAULT 0,
    deleted BOOLEAN NOT NULL DEFAULT 0,
    mhash TEXT,
    mtime INTEGER,
    size INTEGER,
    UNIQUE(vid, pathname)
);

-- Merge state tracking (VMERGE)
CREATE TABLE IF NOT EXISTS vmerge(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    merge INTEGER NOT NULL REFERENCES manifest(rid),
    mhash TEXT NOT NULL,
    merge_type INTEGER NOT NULL DEFAULT 0,
    is_baseline BOOLEAN NOT NULL DEFAULT 0,
    UNIQUE(merge)
);

Phase 1: Version Control Operations ✅ Completed

Implemented Operations

Security Enhancements

Code Quality Improvements

Phase 1.5: VFILE Working Directory Tracking ✅ Completed

The VFILE system provides efficient working directory state tracking using SQLite tables. This mirrors Fossil's vfile.c implementation.

Implemented Features

Test Coverage

See doc_cambria/CAMBRIA_VFILE_IMPL.md for detailed implementation documentation.

Next Steps: Phase 2 (CLI & User Interface)

Current Task: Implement doc_cambria/CAMBRIA_CLI_PLAN.md

Key Fossil → Go Mappings

Fossil Module Cambria Package Responsibility
src/content.c pkg/store/blob.go Content storage
src/manifest.c pkg/artifact/manifest.go Manifest parsing and generation
src/db.c pkg/store/ Database operations (via DBTX)
src/checkin.c pkg/vcs/checkin.go High-level commit creation
src/checkout.c pkg/vcs/checkout.go High-level checkout to filesystem
src/add.c pkg/vcs/add.go File addition to version control
src/diff.c pkg/vcs/diff.go Diff computation
src/vfile.c pkg/vcs/vfile.go VFILE system for working directory tracking
src/vfile.c pkg/vcs/workdir.go Working directory scanning (uses vfile)

Critical Reminders for Agents

  1. Use the Repository API: Do not call pkg/store functions directly for VCS operations. Use the methods on the vcs.Repository struct.
  2. Embrace Transactions: When adding new multi-step database logic, use the tx, err := repo.DB().Begin() pattern.
  3. CGo is Required: The SQLite driver requires CGo. Ensure CGO_ENABLED=1.
  4. Test Everything: All new functionality must be accompanied by tests in the same package. Use the setupTestRepo helper in pkg/vcs for integration-style tests.
  5. Keep It Simple: Follow the YAGNI principle. Don't add abstractions unless necessary.
  6. Content-Addressed: Remember that a blob's UUID is always its SHA-256 hash.
  7. Immutable Blobs: Never modify existing blob records.
  8. Path Security: Always validate user-provided file paths to prevent directory traversal attacks. Use the validation functions in checkout.go and add.go as examples.
  9. Modern Go APIs: Use os.* functions instead of deprecated ioutil.* functions.
  10. Dependencies: The project uses minimal external dependencies. Currently only github.com/mattn/go-sqlite3 (SQLite driver) and github.com/sergi/go-diff (diff library) are used.

Development Commands

# Build all packages
go build ./...

# Run all tests
go test ./...

# Run tests with coverage
go test -cover ./...

# Run tests with race detector (CRITICAL before submitting)
go test -race ./...

# Format code
go fmt ./...

# Static analysis
go vet ./...