Establishes Arbor as a Kubernetes-native git server with event-sourced metadata, designed for AI-assisted software development workflows. Key aspects: - Event sourcing for all metadata (issues, PRs, reviews) - Gitaly-style git storage for horizontal scaling - DDD bounded contexts (Repository, Collaboration, Planning, Identity) - First-class AI integration with structured issue data - Built on Aether and IRIS Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
137 lines
3.9 KiB
Markdown
137 lines
3.9 KiB
Markdown
# 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
|