diff --git a/internal/cmd/install.go b/internal/cmd/install.go index 8efb6a72..b34d8465 100644 --- a/internal/cmd/install.go +++ b/internal/cmd/install.go @@ -17,12 +17,14 @@ import ( ) var ( - installForce bool - installName string - installNoBeads bool - installGit bool - installGitHub string - installPrivate bool + installForce bool + installName string + installOwner string + installPublicName string + installNoBeads bool + installGit bool + installGitHub string + installPrivate bool ) var installCmd = &cobra.Command{ @@ -56,6 +58,8 @@ Examples: func init() { installCmd.Flags().BoolVarP(&installForce, "force", "f", false, "Overwrite existing HQ") installCmd.Flags().StringVarP(&installName, "name", "n", "", "Town name (defaults to directory name)") + installCmd.Flags().StringVar(&installOwner, "owner", "", "Owner email for entity identity (defaults to git config user.email)") + installCmd.Flags().StringVar(&installPublicName, "public-name", "", "Public display name (defaults to town name)") installCmd.Flags().BoolVar(&installNoBeads, "no-beads", false, "Skip town beads initialization") installCmd.Flags().BoolVar(&installGit, "git", false, "Initialize git with .gitignore") installCmd.Flags().StringVar(&installGitHub, "github", "", "Create GitHub repo (format: owner/repo)") @@ -115,12 +119,29 @@ func runInstall(cmd *cobra.Command, args []string) error { } fmt.Printf(" ✓ Created mayor/\n") + // Determine owner (defaults to git user.email) + owner := installOwner + if owner == "" { + out, err := exec.Command("git", "config", "user.email").Output() + if err == nil { + owner = strings.TrimSpace(string(out)) + } + } + + // Determine public name (defaults to town name) + publicName := installPublicName + if publicName == "" { + publicName = townName + } + // Create town.json in mayor/ townConfig := &config.TownConfig{ - Type: "town", - Version: config.CurrentTownVersion, - Name: townName, - CreatedAt: time.Now(), + Type: "town", + Version: config.CurrentTownVersion, + Name: townName, + Owner: owner, + PublicName: publicName, + CreatedAt: time.Now(), } townPath := filepath.Join(mayorDir, "town.json") if err := config.SaveTownConfig(townPath, townConfig); err != nil { diff --git a/internal/config/types.go b/internal/config/types.go index 8f799b10..fe63f2c9 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -8,10 +8,12 @@ import ( // TownConfig represents the main town identity (mayor/town.json). type TownConfig struct { - Type string `json:"type"` // "town" - Version int `json:"version"` // schema version - Name string `json:"name"` // town identifier - CreatedAt time.Time `json:"created_at"` + Type string `json:"type"` // "town" + Version int `json:"version"` // schema version + Name string `json:"name"` // town identifier (internal) + Owner string `json:"owner,omitempty"` // owner email (entity identity) + PublicName string `json:"public_name,omitempty"` // public display name + CreatedAt time.Time `json:"created_at"` } // MayorConfig represents town-level behavioral configuration (mayor/config.json). @@ -70,7 +72,8 @@ type AgentState struct { } // CurrentTownVersion is the current schema version for TownConfig. -const CurrentTownVersion = 1 +// Version 2: Added Owner and PublicName fields for federation identity. +const CurrentTownVersion = 2 // CurrentRigsVersion is the current schema version for RigsConfig. const CurrentRigsVersion = 1