# Arbor Kubernetes-native git server with event-sourced metadata, built for AI-assisted software development. ## Organization Context This repo is part of Flowmade. See: - [Organization manifesto](https://git.flowmade.one/flowmade-one/architecture/src/branch/main/manifesto.md) - who we are, what we believe - [Vision](./vision.md) - what this specific product does ## Related Projects - [Aether](https://git.flowmade.one/flowmade-one/aether) - Event sourcing runtime (Arbor is built on this) - [IRIS](https://git.flowmade.one/flowmade-one/iris) - UI framework (for Arbor's web interface) - [Architecture](https://git.flowmade.one/flowmade-one/architecture) - AI workflow commands used with Arbor ## Setup ```bash git clone git@git.flowmade.one:flowmade-one/arbor.git cd arbor go mod download ``` Requires NATS server for integration tests: ```bash brew install nats-server nats-server -js ``` ## Project Structure ``` arbor/ ├── cmd/ │ └── arbor/ # Main binary ├── internal/ │ ├── domain/ # DDD aggregates and events │ │ ├── repository/ # Repository aggregate │ │ ├── issue/ # Issue aggregate │ │ ├── pullrequest/# PullRequest aggregate │ │ └── ... │ ├── git/ # Git storage service │ ├── api/ # gRPC and HTTP APIs │ └── projection/ # Read models ├── deploy/ │ └── helm/ # Kubernetes deployment └── web/ # IRIS-based UI ``` ## Development ```bash make build # Build the binary make test # Run tests make lint # Run linters ``` ## Architecture ### Event Sourcing for Metadata All git metadata (issues, PRs, reviews, comments, milestones) is event-sourced using Aether: ```go // Issue aggregate type Issue struct { aether.AggregateBase Title string Description string State IssueState Labels []string } // Commands produce events func (i *Issue) HandleCommand(cmd aether.Command) ([]aether.Event, error) { switch c := cmd.(type) { case *CreateIssue: return []aether.Event{&IssueCreated{...}}, nil case *CloseIssue: return []aether.Event{&IssueClosed{...}}, nil } } // Events rebuild state func (i *Issue) ApplyEvent(evt aether.Event) { switch e := evt.(type) { case *IssueCreated: i.Title = e.Title i.State = Open case *IssueClosed: i.State = Closed } } ``` ### Git Storage Service Inspired by GitLab's Gitaly - a dedicated service that owns git operations: - gRPC API for all git operations - Sharded by consistent hashing on repository path - Local SSD storage per shard (no NFS) - Horizontal scaling via StatefulSet ### Bounded Contexts | Context | Aggregates | Events | |---------|------------|--------| | Repository | Repository, Branch | RepositoryCreated, BranchCreated, CommitPushed | | Collaboration | PullRequest, Review | PullRequestOpened, ReviewSubmitted, PullRequestMerged | | Planning | Issue, Milestone, Release | IssueCreated, IssueClosed, MilestoneCompleted | | Identity | User, Organization | UserCreated, OrganizationCreated, MemberAdded | ### AI Integration Points Arbor exposes structured data for AI assistants: ```go // Issues have structured fields AI can parse type Issue struct { Title string Description string AcceptanceCriteria []Criterion // Testable requirements AffectedFiles []string // Hint for where to look Dependencies []IssueRef // What blocks this VerticalSlice *SliceRef // Parent feature } ``` ## Key Patterns - **Events are truth** - All metadata changes are events, never direct mutations - **Git is separate** - Git storage is a dedicated service, not part of the domain - **DDD aggregates** - Repository, Issue, PullRequest are real aggregates with behavior - **Kubernetes-native** - Designed for K8s from day one, not adapted after