fix(priming): use bootstrap pointers instead of full CLAUDE.md templates

Fresh installs and rig adds were creating full CLAUDE.md files (285 lines
for mayor, ~100 lines for other roles), causing gt doctor to fail the
priming check immediately.

Per the priming architecture, CLAUDE.md should be a minimal bootstrap
pointer (<30 lines) that tells agents to run gt prime. Full context is
injected ephemerally at session start.

Changes:
- install.go: createMayorCLAUDEmd now writes 12-line bootstrap pointer
- manager.go: createRoleCLAUDEmd now writes role-specific bootstrap pointers
  for mayor, refinery, crew, and polecat roles

Note: The AGENTS.md issue mentioned in #316 could not be reproduced - the
code does not appear to create AGENTS.md at rig level. May be from an older
version or different configuration.

Partial fix for #316

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
max
2026-01-10 12:39:53 -08:00
committed by Steve Yegge
parent 064f7b1a40
commit 30984dcf95
2 changed files with 77 additions and 42 deletions

View File

@@ -16,7 +16,6 @@ import (
"github.com/steveyegge/gastown/internal/config" "github.com/steveyegge/gastown/internal/config"
"github.com/steveyegge/gastown/internal/deps" "github.com/steveyegge/gastown/internal/deps"
"github.com/steveyegge/gastown/internal/formula" "github.com/steveyegge/gastown/internal/formula"
"github.com/steveyegge/gastown/internal/session"
"github.com/steveyegge/gastown/internal/shell" "github.com/steveyegge/gastown/internal/shell"
"github.com/steveyegge/gastown/internal/state" "github.com/steveyegge/gastown/internal/state"
"github.com/steveyegge/gastown/internal/style" "github.com/steveyegge/gastown/internal/style"
@@ -310,14 +309,23 @@ func runInstall(cmd *cobra.Command, args []string) error {
} }
func createMayorCLAUDEmd(mayorDir, townRoot string) error { func createMayorCLAUDEmd(mayorDir, townRoot string) error {
townName, _ := workspace.GetTownName(townRoot) // Create a minimal bootstrap pointer instead of full context.
return templates.CreateMayorCLAUDEmd( // Full context is injected ephemerally by `gt prime` at session start.
mayorDir, // This keeps the on-disk file small (<30 lines) per priming architecture.
townRoot, bootstrap := `# Mayor Context
townName,
session.MayorSessionName(), > **Recovery**: Run ` + "`gt prime`" + ` after compaction, clear, or new session
session.DeaconSessionName(),
) Full context is injected by ` + "`gt prime`" + ` at session start.
## Quick Reference
- Check mail: ` + "`gt mail inbox`" + `
- Check rigs: ` + "`gt rig list`" + `
- Start patrol: ` + "`gt patrol start`" + `
`
claudePath := filepath.Join(mayorDir, "CLAUDE.md")
return os.WriteFile(claudePath, []byte(bootstrap), 0644)
} }
func writeJSON(path string, data interface{}) error { func writeJSON(path string, data interface{}) error {

View File

@@ -16,8 +16,6 @@ import (
"github.com/steveyegge/gastown/internal/constants" "github.com/steveyegge/gastown/internal/constants"
"github.com/steveyegge/gastown/internal/config" "github.com/steveyegge/gastown/internal/config"
"github.com/steveyegge/gastown/internal/git" "github.com/steveyegge/gastown/internal/git"
"github.com/steveyegge/gastown/internal/templates"
"github.com/steveyegge/gastown/internal/workspace"
) )
// Common errors // Common errors
@@ -900,46 +898,75 @@ func (m *Manager) ListRigNames() []string {
return names return names
} }
// createRoleCLAUDEmd creates a CLAUDE.md file with role-specific context. // createRoleCLAUDEmd creates a minimal bootstrap pointer CLAUDE.md file.
// This ensures each workspace (crew, refinery, mayor) gets the correct prompting, // Full context is injected ephemerally by `gt prime` at session start.
// overriding any CLAUDE.md that may exist in the cloned repository. // This keeps on-disk files small (<30 lines) per the priming architecture.
func (m *Manager) createRoleCLAUDEmd(workspacePath string, role string, rigName string, workerName string) error { func (m *Manager) createRoleCLAUDEmd(workspacePath string, role string, rigName string, workerName string) error {
tmpl, err := templates.New() // Create role-specific bootstrap pointer
if err != nil { var bootstrap string
return err switch role {
} case "mayor":
bootstrap = `# Mayor Context (` + rigName + `)
// Get town name for session names > **Recovery**: Run ` + "`gt prime`" + ` after compaction, clear, or new session
townName, _ := workspace.GetTownName(m.townRoot)
// Get default branch from rig config (default to "main" if not set) Full context is injected by ` + "`gt prime`" + ` at session start.
defaultBranch := "main" `
if rigName != "" { case "refinery":
rigPath := filepath.Join(m.townRoot, rigName) bootstrap = `# Refinery Context (` + rigName + `)
if rigCfg, err := LoadRigConfig(rigPath); err == nil && rigCfg.DefaultBranch != "" {
defaultBranch = rigCfg.DefaultBranch > **Recovery**: Run ` + "`gt prime`" + ` after compaction, clear, or new session
Full context is injected by ` + "`gt prime`" + ` at session start.
## Quick Reference
- Check MQ: ` + "`gt mq list`" + `
- Process next: ` + "`gt mq process`" + `
`
case "crew":
name := workerName
if name == "" {
name = "worker"
} }
} bootstrap = `# Crew Context (` + rigName + `/` + name + `)
data := templates.RoleData{ > **Recovery**: Run ` + "`gt prime`" + ` after compaction, clear, or new session
Role: role,
RigName: rigName,
TownRoot: m.townRoot,
TownName: townName,
WorkDir: workspacePath,
DefaultBranch: defaultBranch,
Polecat: workerName, // Used for crew member name as well
MayorSession: fmt.Sprintf("gt-%s-mayor", townName),
DeaconSession: fmt.Sprintf("gt-%s-deacon", townName),
}
content, err := tmpl.RenderRole(role, data) Full context is injected by ` + "`gt prime`" + ` at session start.
if err != nil {
return err ## Quick Reference
- Check hook: ` + "`gt hook`" + `
- Check mail: ` + "`gt mail inbox`" + `
`
case "polecat":
name := workerName
if name == "" {
name = "worker"
}
bootstrap = `# Polecat Context (` + rigName + `/` + name + `)
> **Recovery**: Run ` + "`gt prime`" + ` after compaction, clear, or new session
Full context is injected by ` + "`gt prime`" + ` at session start.
## Quick Reference
- Check hook: ` + "`gt hook`" + `
- Report done: ` + "`gt done`" + `
`
default:
bootstrap = `# Agent Context
> **Recovery**: Run ` + "`gt prime`" + ` after compaction, clear, or new session
Full context is injected by ` + "`gt prime`" + ` at session start.
`
} }
claudePath := filepath.Join(workspacePath, "CLAUDE.md") claudePath := filepath.Join(workspacePath, "CLAUDE.md")
return os.WriteFile(claudePath, []byte(content), 0644) return os.WriteFile(claudePath, []byte(bootstrap), 0644)
} }
// createPatrolHooks creates .claude/settings.json with hooks for patrol roles. // createPatrolHooks creates .claude/settings.json with hooks for patrol roles.