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:
@@ -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
|
||||
|
||||
---
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.**
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user