From 1e6a3637578b2c03dba1b89e3e08efdc8eb73549 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Fri, 19 Dec 2025 12:02:04 -0800 Subject: [PATCH] docs: add harness design documentation (gt-cr9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- docs/architecture.md | 67 +++++--- docs/harness.md | 331 ++++++++++++++++++++++++++++++++++++++++ internal/cmd/install.go | 12 +- 3 files changed, 386 insertions(+), 24 deletions(-) create mode 100644 docs/harness.md diff --git a/docs/architecture.md b/docs/architecture.md index de916809..d2e25fee 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -45,12 +45,28 @@ graph TB ## Core Concepts -### Town +### Harness (Town) -A **Town** is a complete Gas Town installation - the workspace where everything lives. A town contains: -- Town configuration (`config/` directory) -- Mayor's home (`mayor/` directory at town level) -- One or more **Rigs** (managed project repositories) +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: +- **Harness** = physical (the directory at `~/gt/`) +- **Town** = logical (the Gas Town workspace concept) + +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 @@ -216,25 +232,33 @@ This enables "Engineer in a Box" - polecats that execute structured workflows wi ## Directory Structure -### Town Level +### Harness Level + +The harness (town root) is created by `gt install`: ``` -~/gt/ # Town root (Gas Town harness) -├── CLAUDE.md # Mayor role prompting (at town root) +~/gt/ # HARNESS ROOT (Gas Town installation) +├── CLAUDE.md # Mayor role context (runs from here) ├── .beads/ # Town-level beads (prefix: gm-) │ ├── beads.db # Mayor mail, coordination, handoffs │ └── config.yaml │ -├── mayor/ # Mayor's HOME at town level +├── mayor/ # Mayor configuration and state │ ├── town.json # {"type": "town", "name": "..."} │ ├── rigs.json # Registry of managed rigs -│ └── state.json # Mayor state (NO mail/ directory) +│ └── state.json # Mayor agent state │ -├── gastown/ # A rig (project container) -└── wyvern/ # Another rig +├── rigs/ # Standard location for rigs +│ ├── gastown/ # A rig (project container) +│ └── wyvern/ # Another 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 @@ -316,19 +340,19 @@ graph TB ### 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) -├── CLAUDE.md # Mayor role prompting +~/gt/ # HARNESS ROOT (Gas Town installation) +├── CLAUDE.md # Mayor role context ├── .beads/ # Town-level beads (gm-* prefix) │ ├── beads.db # Mayor mail, coordination │ └── config.yaml │ -├── mayor/ # Mayor's home (at town level) +├── mayor/ # Mayor configuration and state │ ├── town.json # {"type": "town", "name": "..."} │ ├── 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) │ ├── config.json # Rig configuration @@ -1042,10 +1066,13 @@ This ensures all agents in the rig share a single beads database, separate from ## CLI Commands -### Town Management +### Harness Management ```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 --fix # Auto-fix issues ``` diff --git a/docs/harness.md b/docs/harness.md new file mode 100644 index 00000000..ad7a2d54 --- /dev/null +++ b/docs/harness.md @@ -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 +│ +└── / # 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 `/.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 ` | +| Initialize git | `gt git-init` | +| Add rig | `gt rig add ` | +| Check health | `gt doctor` | +| View status | `gt status` | diff --git a/internal/cmd/install.go b/internal/cmd/install.go index 13cf701a..61fffa6a 100644 --- a/internal/cmd/install.go +++ b/internal/cmd/install.go @@ -30,14 +30,18 @@ var installCmd = &cobra.Command{ Short: "Create a new Gas Town harness (workspace)", 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) - - mayor/ Mayor config and state - - rigs/ Managed rig clones (created by 'gt rig add') - - .beads/ Town-level beads DB (mayor mail, coordination) + - mayor/ Mayor config, state, and rig registry + - rigs/ Managed rig containers (created by 'gt rig add') + - .beads/ Town-level beads DB (gm-* prefix for mayor mail) 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: gt install ~/gt # Create harness at ~/gt gt install . --name my-workspace # Initialize current dir