# Role Template Management Strategy **Research Date:** 2026-01-26 **Researcher:** kerosene (gastown/crew) **Status:** Analysis complete, recommendation provided ## Executive Summary Gas Town currently has **two competing mechanisms** for managing role context, leading to divergent content and maintenance complexity: 1. **Embedded templates** (`internal/templates/roles/*.md.tmpl`) - source of truth in binary 2. **Local-fork edits** - direct modifications to runtime `CLAUDE.md` files Additionally, there's a **third mechanism** for operational config that works well: 3. **Role config overrides** (`internal/config/roles.go`) - TOML-based config override chain **Recommendation:** Extend the TOML override pattern to support template content sections, unifying all customization under one mechanism. --- ## Inventory: Current Mechanisms ### 1. Embedded Templates (internal/templates/roles/*.md.tmpl) **Location:** `internal/templates/roles/` **Files:** - `mayor.md.tmpl` (337 lines) - `crew.md.tmpl` (17,607 bytes) - `polecat.md.tmpl` (17,527 bytes) - `witness.md.tmpl` (11,746 bytes) - `refinery.md.tmpl` (13,525 bytes) - `deacon.md.tmpl` (13,727 bytes) - `boot.md.tmpl` (4,445 bytes) **How it works:** - Templates are embedded into the binary via `//go:embed` directive - `gt prime` command renders templates with role-specific data (TownRoot, RigName, etc.) - Output is printed to stdout, where Claude picks it up as context - Uses Go template syntax: `{{ .TownRoot }}`, `{{ .RigName }}`, etc. **Code path:** `templates.New()` → `tmpl.RenderRole()` → stdout ### 2. Local-Fork Edits (Runtime CLAUDE.md) **Location:** Various agent directories (e.g., `mayor/CLAUDE.md`, `/crew//CLAUDE.md`) **How it works:** - `gt install` creates minimal bootstrap CLAUDE.md (~15 lines) via `createMayorCLAUDEmd()` - Bootstrap content just says "Run `gt prime` for full context" - THEN humans/agents directly edit these files with custom content - These edits are committed to the town's git repo **Example:** Mayor's CLAUDE.md grew from bootstrap to 532 lines **Key local-fork commit:** ``` 1cdbc27 docs: Enhance Mayor role template with coordination system knowledge (sc-n2oiz) ``` This commit added ~500 lines to `mayor/CLAUDE.md` including: - Colony Model (why Gas Town uses coordinated specialists) - Escalation Patterns (Witness vs Mayor responsibilities) - Decision Flow (when to use polecats vs crew) - Multi-phase Orchestration - Monitoring without Micromanaging - Teaching GUPP patterns - Communication Patterns - Speed Asymmetry **None of this content exists in the embedded template** - it's purely local-fork. ### 3. Role Config Overrides (TOML files) **Location:** - Built-in: `internal/config/roles/*.toml` (embedded in binary) - Town-level: `/roles/.toml` (optional override) - Rig-level: `/roles/.toml` (optional override) **Resolution order (later wins):** 1. Built-in defaults (embedded) 2. Town-level overrides 3. Rig-level overrides **What it handles:** ```toml # Example: mayor.toml role = "mayor" scope = "town" nudge = "Check mail and hook status, then act accordingly." prompt_template = "mayor.md.tmpl" [session] pattern = "hq-mayor" work_dir = "{town}" needs_pre_sync = false start_command = "exec claude --dangerously-skip-permissions" [env] GT_ROLE = "mayor" GT_SCOPE = "town" [health] ping_timeout = "30s" consecutive_failures = 3 kill_cooldown = "5m" stuck_threshold = "1h" ``` **What it DOES NOT handle:** - Template content (the actual markdown context) - The `prompt_template` field just names which .md.tmpl to use **Implementation:** `LoadRoleDefinition()` in `roles.go` handles the override chain with `mergeRoleDefinition()`. --- ## Analysis: Trade-offs ### Embedded Templates | Pros | Cons | |------|------| | Single source of truth in binary | Requires recompile for changes | | Consistent across all installations | No per-town customization | | Supports placeholder substitution | Can't add town-specific sections | | Version-controlled in gastown repo | Changes don't propagate to existing installs | ### Local-Fork Edits | Pros | Cons | |------|------| | Per-installation customization | Diverges from template source | | No recompile needed | Manual sync to keep up with template changes | | Town-specific content | Each install is unique snowflake | | Immediate effect | Template improvements don't propagate | ### Role Config Overrides | Pros | Cons | |------|------| | Clean override chain | Only handles operational config | | Town/rig level customization | Doesn't handle template content | | Merge semantics (not replace) | - | | No recompile needed | - | --- ## Problem Statement The current situation creates **three-way divergence**: ``` ┌──────────────────────────────────────────┐ │ Embedded Template (mayor.md.tmpl) │ │ 337 lines - "official" content │ └──────────────────────────────────────────┘ │ │ gt prime renders │ BUT doesn't include │ local-fork additions v ┌──────────────────────────────────────────────────────────────────┐ │ Runtime CLAUDE.md (mayor/CLAUDE.md) │ │ 532 lines - has ~200 lines of local-fork content │ │ INCLUDING: Colony Model, Escalation Patterns, etc. │ └──────────────────────────────────────────────────────────────────┘ ``` **Issues:** 1. When `gt prime` runs, it outputs the embedded template (337 lines) 2. The local-fork content (Colony Model, etc.) is in `mayor/CLAUDE.md` 3. Claude Code reads BOTH via `CLAUDE.md` + startup hooks 4. But the embedded template and local CLAUDE.md overlap/conflict 5. Template improvements in new gt versions don't include local-fork content 6. Local-fork improvements aren't shared with other installations --- ## Recommendation: Unified Override System **Extend the existing TOML override mechanism to support template content sections.** ### Proposed Design ```toml # /roles/mayor.toml (town-level override) # Existing operational overrides work as-is [health] stuck_threshold = "2h" # Town needs longer threshold # NEW: Template content sections [content] # Append sections after the embedded template append = """ ## The Colony Model: Why Gas Town Works Gas Town rejects the "super-ant" model... [rest of content] """ # OR reference a file append_file = "mayor-additions.md" # OR override specific sections by ID [content.sections.escalation] replace = """ ## Escalation Patterns: What to Handle vs Delegate ...[custom content]... """ ``` ### Why This Works 1. **Single source of truth**: Embedded templates remain canonical 2. **Clean override semantics**: Town/rig can append or replace sections 3. **Existing infrastructure**: Uses the same TOML loading + merge pattern 4. **No recompile**: Content overrides are runtime files 5. **Shareable**: Town-level overrides can be committed to town repo 6. **Migrateable**: Existing local-fork content can move to `[content]` sections ### Implementation Path 1. **Phase 1**: Add `[content]` support to role config - Parse `append`, `append_file`, `replace_sections` fields - Apply after template rendering in `outputPrimeContext()` 2. **Phase 2**: Migrate local-fork content - Extract custom sections from `mayor/CLAUDE.md` - Move to `/roles/mayor.toml` `[content]` section - Reduce `mayor/CLAUDE.md` back to bootstrap pointer 3. **Phase 3**: Document the pattern - How to add town-specific guidance - How to share improvements back to embedded templates --- ## Alternative Considered: Pure Template Approach **Idea:** Move all content into embedded templates, remove local CLAUDE.md entirely. **Rejected because:** - Can't support per-town customization (e.g., different escalation policies) - Requires recompile for any content change - Forces all installations to be identical - Doesn't leverage existing override infrastructure --- ## Files Involved For implementation, these files would need modification: | File | Change | |------|--------| | `internal/config/roles.go` | Add `[content]` parsing to `RoleDefinition` | | `internal/cmd/prime_output.go` | Apply content overrides after template render | | `internal/templates/templates.go` | Potentially add section markers for replace | | `internal/cmd/install.go` | Update bootstrap to not create full CLAUDE.md | --- ## Summary | Approach | Verdict | |----------|---------| | **Embedded templates only** | Insufficient - no customization | | **Local-fork edits** | Current state - creates divergence | | **TOML content overrides** | **Recommended** - unifies all customization | The TOML content override approach leverages existing infrastructure, provides clean semantics, and allows both standardization (embedded templates) and customization (override sections).