Property Layers: Multi-Level Configuration
Implementation guide for Gas Town’s configuration system. Created: 2025-01-06
Overview
Section titled “Overview”Gas Town uses a layered property system for configuration. Properties are looked up through multiple layers, with earlier layers overriding later ones. This enables both local control and global coordination.
The Four Layers
Section titled “The Four Layers”┌─────────────────────────────────────────────────────────────┐│ 1. WISP LAYER (transient, town-local) ││ Location: <rig>/.beads-wisp/config/ ││ Synced: Never ││ Use: Temporary local overrides │└─────────────────────────────┬───────────────────────────────┘ │ if missing ▼┌─────────────────────────────────────────────────────────────┐│ 2. RIG BEAD LAYER (persistent, synced globally) ││ Location: <rig>/.beads/ (rig identity bead labels) ││ Synced: Via git (all clones see it) ││ Use: Project-wide operational state │└─────────────────────────────┬───────────────────────────────┘ │ if missing ▼┌─────────────────────────────────────────────────────────────┐│ 3. TOWN DEFAULTS ││ Location: ~/gt/config.json or ~/gt/.beads/ ││ Synced: N/A (per-town) ││ Use: Town-wide policies │└─────────────────────────────┬───────────────────────────────┘ │ if missing ▼┌─────────────────────────────────────────────────────────────┐│ 4. SYSTEM DEFAULTS (compiled in) ││ Use: Fallback when nothing else specified │└─────────────────────────────────────────────────────────────┘Lookup Behavior
Section titled “Lookup Behavior”Override Semantics (Default)
Section titled “Override Semantics (Default)”For most properties, the first non-nil value wins:
func GetConfig(key string) interface{} { if val := wisp.Get(key); val != nil { if val == Blocked { return nil } return val } if val := rigBead.GetLabel(key); val != nil { return val } if val := townDefaults.Get(key); val != nil { return val } return systemDefaults[key]}Stacking Semantics (Integers)
Section titled “Stacking Semantics (Integers)”For integer properties, values from wisp and bead layers add to the base:
func GetIntConfig(key string) int { base := getBaseDefault(key) // Town or system default beadAdj := rigBead.GetInt(key) // 0 if missing wispAdj := wisp.GetInt(key) // 0 if missing return base + beadAdj + wispAdj}This enables temporary adjustments without changing the base value.
Blocking Inheritance
Section titled “Blocking Inheritance”You can explicitly block a property from being inherited:
gt rig config set gastown auto_restart --blockThis creates a “blocked” marker in the wisp layer. Even if the rig bead
or defaults say auto_restart: true, the lookup returns nil.
Rig Identity Beads
Section titled “Rig Identity Beads”Each rig has an identity bead for operational state:
id: gt-rig-gastowntype: rigname: gastownprefix: gt
labels: - status:operational - priority:normalThese beads sync via git, so all clones of the rig see the same state.
Two-Level Rig Control
Section titled “Two-Level Rig Control”Level 1: Park (Local, Ephemeral)
Section titled “Level 1: Park (Local, Ephemeral)”gt rig park gastown # Stop services, daemon won't restartgt rig unpark gastown # Allow services to run- Stored in wisp layer (
.beads-wisp/config/) - Only affects this town
- Disappears on cleanup
- Use: Local maintenance, debugging
Level 2: Dock (Global, Persistent)
Section titled “Level 2: Dock (Global, Persistent)”gt rig dock gastown # Set status:docked label on rig beadgt rig undock gastown # Remove label- Stored on rig identity bead
- Syncs to all clones via git
- Permanent until explicitly changed
- Use: Project-wide maintenance, coordinated downtime
Daemon Behavior
Section titled “Daemon Behavior”The daemon checks both levels before auto-restarting:
func shouldAutoRestart(rig *Rig) bool { status := rig.GetConfig("status") if status == "parked" || status == "docked" { return false } return true}Configuration Keys
Section titled “Configuration Keys”| Key | Type | Behavior | Description |
|---|---|---|---|
status | string | Override | operational/parked/docked |
auto_restart | bool | Override | Daemon auto-restart behavior |
max_polecats | int | Override | Maximum concurrent polecats |
priority_adjustment | int | Stack | Scheduling priority modifier |
maintenance_window | string | Override | When maintenance allowed |
dnd | bool | Override | Do not disturb mode |
Commands
Section titled “Commands”View Configuration
Section titled “View Configuration”gt rig config show gastown # Show effective config (all layers)gt rig config show gastown --layer # Show which layer each value comes fromSet Configuration
Section titled “Set Configuration”# Set in wisp layer (local, ephemeral)gt rig config set gastown key value
# Set in bead layer (global, permanent)gt rig config set gastown key value --global
# Block inheritancegt rig config set gastown key --block
# Clear from wisp layergt rig config unset gastown keyRig Lifecycle
Section titled “Rig Lifecycle”gt rig park gastown # Local: stop + prevent restartgt rig unpark gastown # Local: allow restart
gt rig dock gastown # Global: mark as offlinegt rig undock gastown # Global: mark as operational
gt rig status gastown # Show current stateExamples
Section titled “Examples”Temporary Priority Boost
Section titled “Temporary Priority Boost”# Base priority: 0 (from defaults)# Give this rig temporary priority boost for urgent work
gt rig config set gastown priority_adjustment 10
# Effective priority: 0 + 10 = 10# When done, clear it:
gt rig config unset gastown priority_adjustmentLocal Maintenance
Section titled “Local Maintenance”# I'm upgrading the local clone, don't restart servicesgt rig park gastown
# ... do maintenance ...
gt rig unpark gastownProject-Wide Maintenance
Section titled “Project-Wide Maintenance”# Major refactor in progress, all clones should pausegt rig dock gastown
# Syncs via git - other towns see the rig as dockedbd sync
# When done:gt rig undock gastownbd syncBlock Auto-Restart Locally
Section titled “Block Auto-Restart Locally”# Rig bead says auto_restart: true# But I'm debugging and don't want that here
gt rig config set gastown auto_restart --block
# Now auto_restart returns nil for this town onlyImplementation Notes
Section titled “Implementation Notes”Wisp Storage
Section titled “Wisp Storage”Wisp config stored in .beads-wisp/config/<rig>.json:
{ "rig": "gastown", "values": { "status": "parked", "priority_adjustment": 10 }, "blocked": ["auto_restart"]}Rig Bead Labels
Section titled “Rig Bead Labels”Rig operational state stored as labels on the rig identity bead:
bd label add gt-rig-gastown status:dockedbd label remove gt-rig-gastown status:dockedDaemon Integration
Section titled “Daemon Integration”The daemon’s lifecycle manager checks config before starting services:
func (d *Daemon) maybeStartRigServices(rig string) { r := d.getRig(rig)
status := r.GetConfig("status") if status == "parked" || status == "docked" { log.Info("Rig %s is offline, skipping auto-start", rig) return }
d.ensureWitness(rig) d.ensureRefinery(rig)}Related Documents
Section titled “Related Documents”~/gt/docs/hop/PROPERTY-LAYERS.md- Strategic architecturewisp-architecture.md- Wisp system designagent-as-bead.md- Agent identity beads (similar pattern)
