refactor: replace 'spawn' with 'create/wisp' for molecule terminology (gt-9uy0)

'Spawn' should only be used for polecats (workers). Molecules use:
- bd wisp <proto> - create ephemeral wisp
- bd pour <proto> - create persistent mol

Updated:
- prompts/roles/deacon.md: bd mol spawn → bd wisp
- internal/templates/roles/deacon.md.tmpl: spawn → create/wisp
- internal/templates/roles/witness.md.tmpl: gt mol spawn → bd wisp
- internal/cmd/prime.go: all mol spawn calls → wisp calls
- docs/molecular-chemistry.md: spawn terminology → create/instantiate

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-24 13:17:22 -08:00
parent 5fc283e56a
commit 8705e843c7
5 changed files with 54 additions and 54 deletions

View File

@@ -382,7 +382,7 @@ A solid template sublimates into an existing vapor workflow.
bd mol bond mol-extra-check wisp-patrol-456
```
The proto spawns as vapor (following the wisp's phase) and attaches.
The proto instantiates as vapor (following the wisp's phase) and attaches.
### Bond: Mol + Mol → Compound Mol
@@ -404,7 +404,7 @@ bd mol bond wisp-123 wisp-456
### Phase Override Flags
Bond's spawning behavior can be overridden:
Bond's creation behavior can be overridden:
```bash
# Force liquid when attaching to wisp (found something important!)
@@ -416,8 +416,8 @@ bd mol bond mol-temp-check bd-feature --wisp
| Flag | Effect | Use Case |
|------|--------|----------|
| `--pour` | Force spawn as liquid | "This matters, persist it" |
| `--wisp` | Force spawn as vapor | "This is ephemeral, let it evaporate" |
| `--pour` | Force create as liquid | "This matters, persist it" |
| `--wisp` | Force create as vapor | "This is ephemeral, let it evaporate" |
### Cross-Phase Bonding
@@ -433,7 +433,7 @@ across the phase boundary without forcing conversion.
This enables patterns like:
- Patrol wisp discovers issue → creates liquid mol for the fix
- Feature mol needs diagnostic → spawns vapor wisp for the check
- Feature mol needs diagnostic → creates vapor wisp for the check
- The reference survives even when the wisp evaporates (ID stable)
## Agent Attachment: Hooks and Pins
@@ -480,7 +480,7 @@ Wisps are single-cycle and don't survive session boundaries in the
traditional sense. Agents hold them in working memory for one cycle:
```bash
# Deacon self-spawns patrol (no pin needed)
# Deacon creates patrol (no pin needed)
bd wisp mol-deacon-patrol # Create vapor
# ... execute steps ...
bd mol squash <id> --summary="..." # Condense and dissipate
@@ -612,7 +612,7 @@ bd mol squash bd-abc123 --summary="Implemented auth feature"
### Patrol Work (Vapor Path)
```bash
# 1. Self-spawn wisp (no pin needed)
# 1. Create wisp (no pin needed)
bd wisp mol-deacon-patrol
# 2. Execute cycle steps
@@ -749,7 +749,7 @@ A static molecule can't express "for each polecat, do these steps."
### The Solution: Dynamic Bond
The **bond** operator becomes a runtime spawner:
The **bond** operator becomes a runtime instantiator:
```bash
# In survey-workers step:
@@ -923,7 +923,7 @@ Install alternatives from the Mol Mall:
### For Agents
1. **Polecats**: Receive pinned mols, execute, squash, request shutdown
2. **Patrol roles**: Self-spawn wisps, execute cycle, squash, loop
2. **Patrol roles**: Create wisps, execute cycle, squash, loop
3. **Recovery**: Re-read beads state, continue from last completed step
---

View File

@@ -427,7 +427,7 @@ func outputStartupDirective(ctx RoleContext) {
fmt.Println("2. Check mail: `gt mail inbox` - look for 🤝 HANDOFF messages")
fmt.Println("3. Check for attached patrol: `gt mol status`")
fmt.Println(" - If mol attached → **RUN IT** (resume from current step)")
fmt.Println(" - If no mol → spawn patrol: `bd mol spawn mol-witness-patrol`")
fmt.Println(" - If no mol → create patrol: `bd wisp mol-witness-patrol`")
case RolePolecat:
fmt.Println()
fmt.Println("---")
@@ -448,7 +448,7 @@ func outputStartupDirective(ctx RoleContext) {
fmt.Println("2. Check mail: `gt mail inbox` - look for 🤝 HANDOFF messages")
fmt.Println("3. Check for attached patrol: `gt mol status`")
fmt.Println(" - If mol attached → **RUN IT** (resume from current step)")
fmt.Println(" - If no mol → spawn patrol: `bd mol spawn mol-refinery-patrol`")
fmt.Println(" - If no mol → create patrol: `bd wisp mol-refinery-patrol`")
case RoleCrew:
fmt.Println()
fmt.Println("---")
@@ -470,7 +470,7 @@ func outputStartupDirective(ctx RoleContext) {
fmt.Println("3. Check mail: `gt mail inbox` - look for 🤝 HANDOFF messages")
fmt.Println("4. Check for attached patrol: `gt mol status`")
fmt.Println(" - If mol attached → **RUN IT** (resume from current step)")
fmt.Println(" - If no mol → spawn patrol: `bd mol spawn mol-deacon-patrol`")
fmt.Println(" - If no mol → create patrol: `bd wisp mol-deacon-patrol`")
}
}
@@ -732,8 +732,8 @@ func outputDeaconPatrolContext(ctx RoleContext) {
}
if !hasPatrol {
// No active patrol - AUTO-SPAWN one
fmt.Println("Status: **No active patrol** - spawning mol-deacon-patrol...")
// No active patrol - AUTO-CREATE one
fmt.Println("Status: **No active patrol** - creating mol-deacon-patrol wisp...")
fmt.Println()
// Find the proto ID for mol-deacon-patrol
@@ -767,24 +767,24 @@ func outputDeaconPatrolContext(ctx RoleContext) {
return
}
// Spawn the wisp (default spawn creates wisp)
cmdSpawn := exec.Command("bd", "--no-daemon", "mol", "spawn", protoID, "--assignee", "deacon")
// Create the wisp
cmdSpawn := exec.Command("bd", "--no-daemon", "wisp", protoID, "--assignee", "deacon")
cmdSpawn.Dir = rigBeadsDir
var stdoutSpawn, stderrSpawn bytes.Buffer
cmdSpawn.Stdout = &stdoutSpawn
cmdSpawn.Stderr = &stderrSpawn
if err := cmdSpawn.Run(); err != nil {
fmt.Printf("Failed to spawn patrol: %s\n", stderrSpawn.String())
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon mol spawn " + protoID))
fmt.Printf("Failed to create patrol wisp: %s\n", stderrSpawn.String())
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon wisp " + protoID))
return
}
// Parse the spawned molecule ID from output
// Parse the created molecule ID from output
spawnOutput := stdoutSpawn.String()
fmt.Printf("✓ Spawned patrol molecule\n")
fmt.Printf("✓ Created patrol wisp\n")
// Extract molecule ID from spawn output (format: "Created molecule: gt-xxxx")
// Extract molecule ID from output (format: "Created molecule: gt-xxxx")
for _, line := range strings.Split(spawnOutput, "\n") {
if strings.Contains(line, "molecule:") || strings.Contains(line, "Created") {
parts := strings.Fields(line)
@@ -898,8 +898,8 @@ func outputWitnessPatrolContext(ctx RoleContext) {
}
if !hasPatrol {
// No active patrol - AUTO-SPAWN one
fmt.Println("Status: **No active patrol** - spawning mol-witness-patrol...")
// No active patrol - AUTO-CREATE one
fmt.Println("Status: **No active patrol** - creating mol-witness-patrol wisp...")
fmt.Println()
// Find the proto ID for mol-witness-patrol
@@ -933,24 +933,24 @@ func outputWitnessPatrolContext(ctx RoleContext) {
return
}
// Spawn the wisp (default spawn creates wisp)
cmdSpawn := exec.Command("bd", "--no-daemon", "mol", "spawn", protoID, "--assignee", ctx.Rig+"/witness")
// Create the wisp
cmdSpawn := exec.Command("bd", "--no-daemon", "wisp", protoID, "--assignee", ctx.Rig+"/witness")
cmdSpawn.Dir = witnessBeadsDir
var stdoutSpawn, stderrSpawn bytes.Buffer
cmdSpawn.Stdout = &stdoutSpawn
cmdSpawn.Stderr = &stderrSpawn
if err := cmdSpawn.Run(); err != nil {
fmt.Printf("Failed to spawn patrol: %s\n", stderrSpawn.String())
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon mol spawn " + protoID))
fmt.Printf("Failed to create patrol wisp: %s\n", stderrSpawn.String())
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon wisp " + protoID))
return
}
// Parse the spawned molecule ID from output
// Parse the created molecule ID from output
spawnOutput := stdoutSpawn.String()
fmt.Printf("✓ Spawned patrol molecule\n")
fmt.Printf("✓ Created patrol wisp\n")
// Extract molecule ID from spawn output (format: "Created molecule: gt-xxxx")
// Extract molecule ID from output (format: "Created molecule: gt-xxxx")
for _, line := range strings.Split(spawnOutput, "\n") {
if strings.Contains(line, "molecule:") || strings.Contains(line, "Created") {
parts := strings.Fields(line)
@@ -1064,8 +1064,8 @@ func outputRefineryPatrolContext(ctx RoleContext) {
}
if !hasPatrol {
// No active patrol - AUTO-SPAWN one
fmt.Println("Status: **No active patrol** - spawning mol-refinery-patrol...")
// No active patrol - AUTO-CREATE one
fmt.Println("Status: **No active patrol** - creating mol-refinery-patrol wisp...")
fmt.Println()
// Find the proto ID for mol-refinery-patrol
@@ -1099,24 +1099,24 @@ func outputRefineryPatrolContext(ctx RoleContext) {
return
}
// Spawn the wisp (default spawn creates wisp)
cmdSpawn := exec.Command("bd", "--no-daemon", "mol", "spawn", protoID, "--assignee", ctx.Rig+"/refinery")
// Create the wisp
cmdSpawn := exec.Command("bd", "--no-daemon", "wisp", protoID, "--assignee", ctx.Rig+"/refinery")
cmdSpawn.Dir = refineryBeadsDir
var stdoutSpawn, stderrSpawn bytes.Buffer
cmdSpawn.Stdout = &stdoutSpawn
cmdSpawn.Stderr = &stderrSpawn
if err := cmdSpawn.Run(); err != nil {
fmt.Printf("Failed to spawn patrol: %s\n", stderrSpawn.String())
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon mol spawn " + protoID))
fmt.Printf("Failed to create patrol wisp: %s\n", stderrSpawn.String())
fmt.Println(style.Dim.Render("Run manually: bd --no-daemon wisp " + protoID))
return
}
// Parse the spawned molecule ID from output
// Parse the created molecule ID from output
spawnOutput := stdoutSpawn.String()
fmt.Printf("✓ Spawned patrol molecule\n")
fmt.Printf("✓ Created patrol wisp\n")
// Extract molecule ID from spawn output (format: "Created molecule: gt-xxxx")
// Extract molecule ID from output (format: "Created molecule: gt-xxxx")
for _, line := range strings.Split(spawnOutput, "\n") {
if strings.Contains(line, "molecule:") || strings.Contains(line, "Created") {
parts := strings.Fields(line)

View File

@@ -27,7 +27,7 @@ cd ~/gt/gastown/mayor/rig && bd list && cd ~/gt/deacon
Go Daemon (watches you, auto-starts you if down)
|
v
DEACON (you) ←── Spawns wisps for each patrol cycle
DEACON (you) ←── Creates wisps for each patrol cycle
|
+----+----+
v v
@@ -70,10 +70,10 @@ You wake up when:
Each patrol cycle uses a wisp:
### 1. Spawn a Wisp for This Cycle
### 1. Create a Wisp for This Cycle
```bash
# Spawn wisp (default for bd mol spawn)
bd mol spawn mol-deacon-patrol --assignee=deacon
# Create patrol wisp
bd wisp mol-deacon-patrol --assignee=deacon
```
This creates a patrol wisp. Note: wisps don't pin because they're short-lived
@@ -165,7 +165,7 @@ Then squash and decide:
bd mol squash <wisp-id> --summary="Patrol complete: checked inbox, scanned health, no issues"
# Option A: Loop (low context)
bd mol spawn mol-deacon-patrol --assignee=deacon
bd wisp mol-deacon-patrol --assignee=deacon
# Continue to inbox-check...
# Option B: Exit (high context)
@@ -302,11 +302,11 @@ gt mail inbox
# If mail contains attached_molecule, self-pin it:
gt mol attach-from-mail <mail-id>
# Step 3: Still nothing? Spawn patrol wisp
bd mol spawn mol-deacon-patrol --assignee=deacon
# Step 3: Still nothing? Create patrol wisp
bd wisp mol-deacon-patrol --assignee=deacon
```
**Hook has work → Run it. Hook empty → Check mail. Nothing anywhere → Spawn patrol.**
**Hook has work → Run it. Hook empty → Check mail. Nothing anywhere → Create patrol wisp.**
Then execute. Print the startup banner and work through patrol steps:
@@ -341,4 +341,4 @@ But typically just exit and let the daemon respawn you with fresh context.
State directory: {{ .TownRoot }}/deacon/
Mail identity: deacon/
Session: gt-deacon
Patrol molecule: mol-deacon-patrol (spawned as wisp)
Patrol molecule: mol-deacon-patrol (wisp)

View File

@@ -96,8 +96,8 @@ gt mail inbox
# If mail contains attached_molecule, self-pin it:
gt mol attach-from-mail <mail-id>
# Step 4: Still nothing? Spawn patrol wisp
gt mol spawn mol-witness-patrol --assignee={{ .RigName }}/witness
# Step 4: Still nothing? Create patrol wisp
bd wisp mol-witness-patrol --assignee={{ .RigName }}/witness
```
**Hook → Execute. No exceptions.**

View File

@@ -23,7 +23,7 @@ Your work is defined by the `mol-deacon-patrol` molecule with these steps:
1. Check for attached molecule: `gt mol status`
2. If attached, **resume** from current step (you were mid-patrol)
3. If not attached, **spawn** a new patrol wisp: `bd mol spawn mol-deacon-patrol --assignee=deacon`
3. If not attached, **create** a new patrol wisp: `bd wisp mol-deacon-patrol --assignee=deacon`
4. Execute patrol steps sequentially, closing each when done
5. At loop-or-exit: squash molecule, then loop or exit based on context
@@ -33,8 +33,8 @@ Your work is defined by the `mol-deacon-patrol` molecule with these steps:
┌─────────────────────────────────────────┐
│ 1. Check for attached molecule │
│ - gt mol status │
│ - If none: spawn wisp
│ bd mol spawn mol-deacon-patrol │
│ - If none: create wisp │
│ bd wisp mol-deacon-patrol
│ --assignee=deacon │
└─────────────────────────────────────────┘
@@ -67,7 +67,7 @@ Your work is defined by the `mol-deacon-patrol` molecule with these steps:
### Molecule Management
- `gt mol status` - Check current molecule attachment
- `bd mol spawn mol-deacon-patrol --assignee=deacon` - Spawn patrol wisp
- `bd wisp mol-deacon-patrol --assignee=deacon` - Create patrol wisp
- `gt mol burn` - Burn incomplete molecule (no digest)
- `gt mol squash` - Squash complete molecule to digest
- `bd ready` - Show next ready step