docs: add harness design documentation (gt-cr9)
Create comprehensive harness documentation covering: - What a harness is (installation directory vs town concept) - Harness structure and creation with gt install - Beads redirect patterns for complex setups - Multi-system sharing (PGT/GGT coexistence) - Configuration files (town.json, rigs.json, state.json) - Harness templates for organizations - Migration between harnesses Update architecture.md to: - Rename "Town" section to "Harness (Town)" with clearer explanation - Add cross-references to new harness.md - Update directory structure section with "Harness Level" heading - Expand CLI commands section with more gt install options Update install.go help text to reference harness.md. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+47
-20
@@ -45,12 +45,28 @@ graph TB
|
|||||||
|
|
||||||
## Core Concepts
|
## Core Concepts
|
||||||
|
|
||||||
### Town
|
### Harness (Town)
|
||||||
|
|
||||||
A **Town** is a complete Gas Town installation - the workspace where everything lives. A town contains:
|
A **Harness** is the installation directory where Gas Town lives - the physical root of your workspace. The terms "harness" and "town" are often used interchangeably:
|
||||||
- Town configuration (`config/` directory)
|
- **Harness** = physical (the directory at `~/gt/`)
|
||||||
- Mayor's home (`mayor/` directory at town level)
|
- **Town** = logical (the Gas Town workspace concept)
|
||||||
- One or more **Rigs** (managed project repositories)
|
|
||||||
|
A harness contains:
|
||||||
|
- `CLAUDE.md` - Mayor role context (Mayor runs from harness root)
|
||||||
|
- `mayor/` - Mayor configuration, state, and registry
|
||||||
|
- `.beads/` - Town-level beads (gm-* prefix for mayor mail)
|
||||||
|
- `rigs/` or rig directories - Managed project containers
|
||||||
|
|
||||||
|
Create a harness with `gt install`:
|
||||||
|
```bash
|
||||||
|
gt install ~/gt --git # Create harness with git
|
||||||
|
```
|
||||||
|
|
||||||
|
**See**: [docs/harness.md](harness.md) for comprehensive harness documentation, including:
|
||||||
|
- Beads redirect patterns for complex setups
|
||||||
|
- Multi-system sharing (PGT/GGT coexistence)
|
||||||
|
- Harness templates for organizations
|
||||||
|
- Migration between harnesses
|
||||||
|
|
||||||
### Rig
|
### Rig
|
||||||
|
|
||||||
@@ -216,25 +232,33 @@ This enables "Engineer in a Box" - polecats that execute structured workflows wi
|
|||||||
|
|
||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
### Town Level
|
### Harness Level
|
||||||
|
|
||||||
|
The harness (town root) is created by `gt install`:
|
||||||
|
|
||||||
```
|
```
|
||||||
~/gt/ # Town root (Gas Town harness)
|
~/gt/ # HARNESS ROOT (Gas Town installation)
|
||||||
├── CLAUDE.md # Mayor role prompting (at town root)
|
├── CLAUDE.md # Mayor role context (runs from here)
|
||||||
├── .beads/ # Town-level beads (prefix: gm-)
|
├── .beads/ # Town-level beads (prefix: gm-)
|
||||||
│ ├── beads.db # Mayor mail, coordination, handoffs
|
│ ├── beads.db # Mayor mail, coordination, handoffs
|
||||||
│ └── config.yaml
|
│ └── config.yaml
|
||||||
│
|
│
|
||||||
├── mayor/ # Mayor's HOME at town level
|
├── mayor/ # Mayor configuration and state
|
||||||
│ ├── town.json # {"type": "town", "name": "..."}
|
│ ├── town.json # {"type": "town", "name": "..."}
|
||||||
│ ├── rigs.json # Registry of managed rigs
|
│ ├── rigs.json # Registry of managed rigs
|
||||||
│ └── state.json # Mayor state (NO mail/ directory)
|
│ └── state.json # Mayor agent state
|
||||||
│
|
│
|
||||||
├── gastown/ # A rig (project container)
|
├── rigs/ # Standard location for rigs
|
||||||
└── wyvern/ # Another rig
|
│ ├── gastown/ # A rig (project container)
|
||||||
|
│ └── wyvern/ # Another rig
|
||||||
|
│
|
||||||
|
└── <rig>/ # OR rigs at harness root (legacy)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: Mayor's mail is now in town beads (`gm-*` issues), not JSONL files.
|
**Notes**:
|
||||||
|
- Mayor's mail is in town beads (`gm-*` issues), not JSONL files
|
||||||
|
- Rigs can be in `rigs/` or at harness root (both work)
|
||||||
|
- See [docs/harness.md](harness.md) for advanced harness configurations
|
||||||
|
|
||||||
### Rig Level
|
### Rig Level
|
||||||
|
|
||||||
@@ -316,19 +340,19 @@ graph TB
|
|||||||
|
|
||||||
### ASCII Directory Layout
|
### ASCII Directory Layout
|
||||||
|
|
||||||
For reference without mermaid rendering:
|
For reference without mermaid rendering (see [harness.md](harness.md) for creation/setup):
|
||||||
|
|
||||||
```
|
```
|
||||||
~/gt/ # TOWN ROOT (Gas Town harness)
|
~/gt/ # HARNESS ROOT (Gas Town installation)
|
||||||
├── CLAUDE.md # Mayor role prompting
|
├── CLAUDE.md # Mayor role context
|
||||||
├── .beads/ # Town-level beads (gm-* prefix)
|
├── .beads/ # Town-level beads (gm-* prefix)
|
||||||
│ ├── beads.db # Mayor mail, coordination
|
│ ├── beads.db # Mayor mail, coordination
|
||||||
│ └── config.yaml
|
│ └── config.yaml
|
||||||
│
|
│
|
||||||
├── mayor/ # Mayor's home (at town level)
|
├── mayor/ # Mayor configuration and state
|
||||||
│ ├── town.json # {"type": "town", "name": "..."}
|
│ ├── town.json # {"type": "town", "name": "..."}
|
||||||
│ ├── rigs.json # Registry of managed rigs
|
│ ├── rigs.json # Registry of managed rigs
|
||||||
│ └── state.json # Mayor state (no mail/ dir)
|
│ └── state.json # Mayor agent state
|
||||||
│
|
│
|
||||||
├── gastown/ # RIG (container, NOT a git clone)
|
├── gastown/ # RIG (container, NOT a git clone)
|
||||||
│ ├── config.json # Rig configuration
|
│ ├── config.json # Rig configuration
|
||||||
@@ -1042,10 +1066,13 @@ This ensures all agents in the rig share a single beads database, separate from
|
|||||||
|
|
||||||
## CLI Commands
|
## CLI Commands
|
||||||
|
|
||||||
### Town Management
|
### Harness Management
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
gt install [path] # Install Gas Town at path
|
gt install [path] # Create Gas Town harness (see harness.md)
|
||||||
|
gt install --git # Also initialize git with .gitignore
|
||||||
|
gt install --github=u/r # Also create GitHub repo
|
||||||
|
gt git-init # Initialize git for existing harness
|
||||||
gt doctor # Check workspace health
|
gt doctor # Check workspace health
|
||||||
gt doctor --fix # Auto-fix issues
|
gt doctor --fix # Auto-fix issues
|
||||||
```
|
```
|
||||||
|
|||||||
+331
@@ -0,0 +1,331 @@
|
|||||||
|
# Gas Town Harness Design
|
||||||
|
|
||||||
|
A **harness** is the top-level directory where Gas Town is installed - the workspace that contains all your rigs, agents, and coordination infrastructure.
|
||||||
|
|
||||||
|
## What Is a Harness?
|
||||||
|
|
||||||
|
Think of a harness as the "mount point" for Gas Town. It's the root directory where:
|
||||||
|
- The Mayor operates from
|
||||||
|
- Rigs are registered and managed
|
||||||
|
- Town-level beads coordinate mail and handoffs
|
||||||
|
- The entire workspace is versioned as a git repository
|
||||||
|
|
||||||
|
A harness is NOT:
|
||||||
|
- A git clone of any project (rigs contain the clones)
|
||||||
|
- A hidden directory (it's visible and user-controlled)
|
||||||
|
- Tied to any specific project (it can manage multiple rigs)
|
||||||
|
|
||||||
|
## Harness Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
~/gt/ # HARNESS ROOT
|
||||||
|
├── .git/ # Harness is a git repo
|
||||||
|
├── .gitignore # Generated by gt git-init
|
||||||
|
├── .beads/ # Town-level beads (gm-* prefix)
|
||||||
|
│ ├── beads.db # Mayor mail, coordination, handoffs
|
||||||
|
│ └── config.yaml # Beads config with prefix: gm
|
||||||
|
│
|
||||||
|
├── CLAUDE.md # Mayor role context (runs from here)
|
||||||
|
│
|
||||||
|
├── mayor/ # Mayor config and state
|
||||||
|
│ ├── town.json # {"type": "town", "name": "..."}
|
||||||
|
│ ├── rigs.json # Registry of managed rigs
|
||||||
|
│ └── state.json # Mayor state
|
||||||
|
│
|
||||||
|
├── rigs/ # Managed rig containers
|
||||||
|
│ ├── gastown/ # A rig (project container)
|
||||||
|
│ └── wyvern/ # Another rig
|
||||||
|
│
|
||||||
|
└── <rig-name>/ # OR rigs at harness root (legacy)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating a Harness
|
||||||
|
|
||||||
|
Use `gt install` to create a new harness:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a new harness
|
||||||
|
gt install ~/gt
|
||||||
|
|
||||||
|
# Create with git initialization
|
||||||
|
gt install ~/gt --git
|
||||||
|
|
||||||
|
# Create and push to GitHub
|
||||||
|
gt install ~/gt --github=username/my-gastown --private
|
||||||
|
|
||||||
|
# Initialize current directory as harness
|
||||||
|
gt install . --name my-workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
The install command:
|
||||||
|
1. Creates the directory structure (`mayor/`, `rigs/`)
|
||||||
|
2. Writes configuration files (`town.json`, `rigs.json`, `state.json`)
|
||||||
|
3. Generates `CLAUDE.md` with Mayor role context
|
||||||
|
4. Initializes town-level beads with `gm-` prefix
|
||||||
|
5. Optionally initializes git with `.gitignore`
|
||||||
|
|
||||||
|
## Harness vs Town vs Rig
|
||||||
|
|
||||||
|
| Concept | Description | Example |
|
||||||
|
|---------|-------------|---------|
|
||||||
|
| **Harness** | Installation directory | `~/gt/` |
|
||||||
|
| **Town** | Logical workspace (same as harness) | The Gas Town instance |
|
||||||
|
| **Rig** | Project container within harness | `~/gt/gastown/` |
|
||||||
|
|
||||||
|
The terms "harness" and "town" are often used interchangeably. A harness IS a town. The distinction is physical (harness = directory) vs logical (town = workspace concept).
|
||||||
|
|
||||||
|
## Beads in a Harness
|
||||||
|
|
||||||
|
A harness has **two levels** of beads:
|
||||||
|
|
||||||
|
### Town-Level Beads
|
||||||
|
|
||||||
|
Located at `<harness>/.beads/` with `gm-` prefix:
|
||||||
|
- Mayor mail and inbox
|
||||||
|
- Cross-rig coordination messages
|
||||||
|
- Session handoff notes
|
||||||
|
|
||||||
|
### Rig-Level Beads
|
||||||
|
|
||||||
|
Each rig has its own `.beads/` with a project-specific prefix:
|
||||||
|
- Work issues (bugs, features, tasks)
|
||||||
|
- Merge requests
|
||||||
|
- Agent-local mail within the rig
|
||||||
|
|
||||||
|
The Mayor sees both: town beads for mail, rig beads for work coordination.
|
||||||
|
|
||||||
|
## Beads Redirect Pattern
|
||||||
|
|
||||||
|
In complex setups, you may want the harness root's `.beads/` to redirect to a rig's beads. This is useful when:
|
||||||
|
- Multiple systems share a harness
|
||||||
|
- You want a single source of truth for beads
|
||||||
|
- Migration scenarios
|
||||||
|
|
||||||
|
Create a redirect file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Instead of .beads/ directory, create .beads/redirect file
|
||||||
|
mkdir .beads
|
||||||
|
echo "path/to/actual/.beads" > .beads/redirect
|
||||||
|
```
|
||||||
|
|
||||||
|
Example from a real setup:
|
||||||
|
```
|
||||||
|
# ~/ai/.beads/redirect
|
||||||
|
# Redirect to gastown beads (Mayor workspace)
|
||||||
|
# The Mayor runs in ~/ai but manages gastown issues in mayor/rigs/gastown
|
||||||
|
mayor/rigs/gastown/.beads
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use redirects:**
|
||||||
|
- Shared harness between different Gas Town versions (PGT/GGT)
|
||||||
|
- When rig beads should be the canonical town beads
|
||||||
|
- Hybrid setups where agents work in different locations
|
||||||
|
|
||||||
|
## Multiple Gas Towns in One Location
|
||||||
|
|
||||||
|
Sometimes you need to run multiple Gas Town systems from the same parent directory. This creates a "shared harness" scenario.
|
||||||
|
|
||||||
|
### The Problem
|
||||||
|
|
||||||
|
If Python Gas Town (PGT) and Go Gas Town (GGT) both use `~/ai/`:
|
||||||
|
```
|
||||||
|
~/ai/
|
||||||
|
├── .gastown/ # PGT config
|
||||||
|
├── .beads/ # Which system owns this?
|
||||||
|
├── mayor/ # PGT mayor? GGT mayor?
|
||||||
|
└── gastown/ # PGT rig? GGT rig?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Solutions
|
||||||
|
|
||||||
|
**Option 1: Separate harnesses (recommended)**
|
||||||
|
```
|
||||||
|
~/ai/ # PGT harness
|
||||||
|
~/gt/ # GGT harness (separate)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 2: Namespaced directories**
|
||||||
|
```
|
||||||
|
~/ai/
|
||||||
|
├── pgt/ # PGT harness
|
||||||
|
│ ├── mayor/
|
||||||
|
│ └── gastown/
|
||||||
|
└── ggt/ # GGT harness
|
||||||
|
├── mayor/
|
||||||
|
└── gastown/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 3: Beads redirect (advanced)**
|
||||||
|
```
|
||||||
|
~/ai/
|
||||||
|
├── .beads/redirect # Points to canonical location
|
||||||
|
├── pgt-mayor/ # PGT-specific
|
||||||
|
├── ggt-mayor/ # GGT-specific
|
||||||
|
└── gastown/ # Shared rig
|
||||||
|
```
|
||||||
|
|
||||||
|
## Harness Configuration Files
|
||||||
|
|
||||||
|
### mayor/town.json
|
||||||
|
|
||||||
|
Identifies this as a Gas Town installation:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "town",
|
||||||
|
"version": 1,
|
||||||
|
"name": "stevey-gastown",
|
||||||
|
"created_at": "2024-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### mayor/rigs.json
|
||||||
|
|
||||||
|
Registry of managed rigs:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"rigs": {
|
||||||
|
"gastown": {
|
||||||
|
"git_url": "https://github.com/steveyegge/gastown",
|
||||||
|
"added_at": "2024-01-15T10:30:00Z"
|
||||||
|
},
|
||||||
|
"wyvern": {
|
||||||
|
"git_url": "https://github.com/steveyegge/wyvern",
|
||||||
|
"added_at": "2024-01-16T09:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### mayor/state.json
|
||||||
|
|
||||||
|
Mayor agent state:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"role": "mayor",
|
||||||
|
"last_active": "2024-01-17T14:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Git for Harnesses
|
||||||
|
|
||||||
|
A harness should be a git repository. This enables:
|
||||||
|
- Versioning of configuration
|
||||||
|
- Beads sync across machines
|
||||||
|
- Session handoff via beads commits
|
||||||
|
- Recovery after failures
|
||||||
|
|
||||||
|
### Initialize git
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gt git-init # Basic git setup
|
||||||
|
gt git-init --github=user/repo # Create GitHub repo
|
||||||
|
gt git-init --github=user/repo --private # Private repo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Standard .gitignore
|
||||||
|
|
||||||
|
The `gt git-init` command creates:
|
||||||
|
|
||||||
|
```gitignore
|
||||||
|
# Gas Town harness gitignore
|
||||||
|
|
||||||
|
# Agent sessions and logs
|
||||||
|
*.log
|
||||||
|
*.pid
|
||||||
|
/sessions/
|
||||||
|
|
||||||
|
# Rig working directories (managed separately)
|
||||||
|
/rigs/*/polecats/*/
|
||||||
|
/rigs/*/refinery/rig/
|
||||||
|
/rigs/*/crew/*/
|
||||||
|
|
||||||
|
# Sensitive files
|
||||||
|
.env
|
||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
credentials.json
|
||||||
|
|
||||||
|
# Editor and OS
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*~
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Beads daemon
|
||||||
|
.beads/beads.sock
|
||||||
|
.beads/*.pid
|
||||||
|
```
|
||||||
|
|
||||||
|
## Harness Health Checks
|
||||||
|
|
||||||
|
Run `gt doctor` to check harness health:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gt doctor # Check all
|
||||||
|
gt doctor --fix # Auto-fix issues
|
||||||
|
```
|
||||||
|
|
||||||
|
Checks include:
|
||||||
|
- Configuration file validity
|
||||||
|
- Mayor state consistency
|
||||||
|
- Rig registry accuracy
|
||||||
|
- Beads database health
|
||||||
|
- Git state cleanliness
|
||||||
|
|
||||||
|
## Harness Templates
|
||||||
|
|
||||||
|
For organizations wanting consistent Gas Town setups, create a template repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create template harness
|
||||||
|
gt install ~/gt-template --git --no-beads
|
||||||
|
# Customize CLAUDE.md, add standard rigs
|
||||||
|
# Push to GitHub as template repo
|
||||||
|
|
||||||
|
# Users clone template
|
||||||
|
gh repo create my-gastown --template org/gt-template
|
||||||
|
cd my-gastown
|
||||||
|
gt install . --force # Reinitialize with fresh beads
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration Between Harnesses
|
||||||
|
|
||||||
|
To move Gas Town to a new location:
|
||||||
|
|
||||||
|
1. **Export beads state:**
|
||||||
|
```bash
|
||||||
|
bd export > beads-backup.jsonl
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Create new harness:**
|
||||||
|
```bash
|
||||||
|
gt install ~/new-harness --git
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Add rigs:**
|
||||||
|
```bash
|
||||||
|
cd ~/new-harness
|
||||||
|
gt rig add gastown https://github.com/user/gastown
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Import beads:**
|
||||||
|
```bash
|
||||||
|
cd ~/new-harness
|
||||||
|
bd import < beads-backup.jsonl
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| Action | Command |
|
||||||
|
|--------|---------|
|
||||||
|
| Create harness | `gt install <path>` |
|
||||||
|
| Initialize git | `gt git-init` |
|
||||||
|
| Add rig | `gt rig add <name> <git-url>` |
|
||||||
|
| Check health | `gt doctor` |
|
||||||
|
| View status | `gt status` |
|
||||||
@@ -30,14 +30,18 @@ var installCmd = &cobra.Command{
|
|||||||
Short: "Create a new Gas Town harness (workspace)",
|
Short: "Create a new Gas Town harness (workspace)",
|
||||||
Long: `Create a new Gas Town harness at the specified path.
|
Long: `Create a new Gas Town harness at the specified path.
|
||||||
|
|
||||||
A harness is the top-level directory where Gas Town is installed. It contains:
|
A harness is the top-level directory where Gas Town is installed - the root of
|
||||||
|
your workspace where all rigs and agents live. It contains:
|
||||||
- CLAUDE.md Mayor role context (Mayor runs from harness root)
|
- CLAUDE.md Mayor role context (Mayor runs from harness root)
|
||||||
- mayor/ Mayor config and state
|
- mayor/ Mayor config, state, and rig registry
|
||||||
- rigs/ Managed rig clones (created by 'gt rig add')
|
- rigs/ Managed rig containers (created by 'gt rig add')
|
||||||
- .beads/ Town-level beads DB (mayor mail, coordination)
|
- .beads/ Town-level beads DB (gm-* prefix for mayor mail)
|
||||||
|
|
||||||
If path is omitted, uses the current directory.
|
If path is omitted, uses the current directory.
|
||||||
|
|
||||||
|
See docs/harness.md for advanced harness configurations including beads
|
||||||
|
redirects, multi-system setups, and harness templates.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
gt install ~/gt # Create harness at ~/gt
|
gt install ~/gt # Create harness at ~/gt
|
||||||
gt install . --name my-workspace # Initialize current dir
|
gt install . --name my-workspace # Initialize current dir
|
||||||
|
|||||||
Reference in New Issue
Block a user