chore: Bump version to 0.4.0
Key fix: Orphan cleanup now skips Claude processes in valid Gas Town tmux sessions (gt-*/hq-*), preventing false kills of witnesses, refineries, and deacon during startup. Updated all component versions: - gt CLI: 0.3.1 → 0.4.0 - npm package: 0.3.0 → 0.4.0 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -62,12 +62,6 @@
|
|||||||
# - github.repo
|
# - github.repo
|
||||||
sync-branch: beads-sync
|
sync-branch: beads-sync
|
||||||
|
|
||||||
# Gas Town custom types (bd-t5o8i)
|
|
||||||
# These types are used by Gas Town infrastructure but are not core beads types.
|
|
||||||
# They will be removed from beads built-in types (bd-find4) and configured here instead.
|
|
||||||
types:
|
|
||||||
custom: "molecule,gate,convoy,merge-request,slot,agent,role,rig,event,message"
|
|
||||||
|
|
||||||
# Cross-project dependencies (gt-o3is)
|
# Cross-project dependencies (gt-o3is)
|
||||||
# Maps project names to paths for external dependency resolution
|
# Maps project names to paths for external dependency resolution
|
||||||
# Format: external:<project>:<capability> in bd dep commands
|
# Format: external:<project>:<capability> in bd dep commands
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
description = """
|
|
||||||
Test molecule for verifying exponential backoff behavior.
|
|
||||||
|
|
||||||
Uses SHORT intervals (2s base, 10s max) so you can observe multiple
|
|
||||||
backoff cycles in under a minute.
|
|
||||||
|
|
||||||
Expected backoff progression:
|
|
||||||
- Cycle 0: 2s
|
|
||||||
- Cycle 1: 4s
|
|
||||||
- Cycle 2: 8s
|
|
||||||
- Cycle 3+: 10s (capped)
|
|
||||||
|
|
||||||
Full backoff cycle observable in ~24 seconds.
|
|
||||||
|
|
||||||
## Running This Test
|
|
||||||
|
|
||||||
1. Create a test agent bead (if not exists):
|
|
||||||
```bash
|
|
||||||
bd create --type=agent --title="Backoff Test Agent" --id=hq-backoff-test
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Run the deacon with this formula, or execute steps manually:
|
|
||||||
```bash
|
|
||||||
gt mol step await-signal --agent-bead hq-backoff-test \
|
|
||||||
--backoff-base 2s --backoff-mult 2 --backoff-max 10s
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Watch the idle counter increment on each timeout:
|
|
||||||
```bash
|
|
||||||
bd show hq-backoff-test --json | jq '.[] | .labels'
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Trigger activity to test signal wake:
|
|
||||||
```bash
|
|
||||||
bd create --title="Wake signal" --silent # Any bd command triggers activity
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Reset idle counter after signal (caller responsibility):
|
|
||||||
```bash
|
|
||||||
bd update hq-backoff-test --set-labels=idle:0
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
formula = "mol-backoff-test"
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
[[steps]]
|
|
||||||
id = "heartbeat"
|
|
||||||
title = "Touch heartbeat"
|
|
||||||
description = """
|
|
||||||
Touch heartbeat to show we're alive.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gt deacon heartbeat "backoff test cycle"
|
|
||||||
```
|
|
||||||
|
|
||||||
This updates the deacon's heartbeat file to signal liveness.
|
|
||||||
"""
|
|
||||||
|
|
||||||
[[steps]]
|
|
||||||
id = "await-signal"
|
|
||||||
title = "Wait with exponential backoff (SHORT intervals)"
|
|
||||||
needs = ["heartbeat"]
|
|
||||||
description = """
|
|
||||||
Wait for activity with exponential backoff using TEST intervals.
|
|
||||||
|
|
||||||
**IMPORTANT**: This uses SHORT intervals for testing:
|
|
||||||
- Base: 2s (production: 60s)
|
|
||||||
- Multiplier: 2
|
|
||||||
- Max: 10s (production: 10m)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gt mol step await-signal --agent-bead hq-backoff-test \
|
|
||||||
--backoff-base 2s --backoff-mult 2 --backoff-max 10s
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected behavior:**
|
|
||||||
|
|
||||||
| Idle Cycles | Timeout |
|
|
||||||
|-------------|---------|
|
|
||||||
| 0 | 2s |
|
|
||||||
| 1 | 4s |
|
|
||||||
| 2 | 8s |
|
|
||||||
| 3+ | 10s |
|
|
||||||
|
|
||||||
**On timeout**: The command auto-increments the `idle:N` label on the agent bead.
|
|
||||||
Continue to the next patrol cycle (loop back to heartbeat).
|
|
||||||
|
|
||||||
**On signal**: Activity was detected. Reset the idle counter:
|
|
||||||
```bash
|
|
||||||
bd update hq-backoff-test --set-labels=idle:0
|
|
||||||
```
|
|
||||||
Then loop back to heartbeat for the next cycle.
|
|
||||||
|
|
||||||
**To exit**: When context is high or testing is complete, exit cleanly.
|
|
||||||
"""
|
|
||||||
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.4.0] - 2026-01-17
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Orphan cleanup skips valid tmux sessions** - `gt orphans kill` and automatic orphan cleanup now check for Claude processes belonging to valid Gas Town tmux sessions (gt-*/hq-*) before killing. This prevents false kills of witnesses, refineries, and deacon during startup when they may temporarily show TTY "?"
|
||||||
|
|
||||||
## [0.3.1] - 2026-01-17
|
## [0.3.1] - 2026-01-17
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -74,6 +74,13 @@ type VersionChange struct {
|
|||||||
|
|
||||||
// versionChanges contains agent-actionable changes for recent versions
|
// versionChanges contains agent-actionable changes for recent versions
|
||||||
var versionChanges = []VersionChange{
|
var versionChanges = []VersionChange{
|
||||||
|
{
|
||||||
|
Version: "0.4.0",
|
||||||
|
Date: "2026-01-17",
|
||||||
|
Changes: []string{
|
||||||
|
"FIX: Orphan cleanup skips valid tmux sessions - Prevents false kills of witnesses/refineries/deacon during startup by checking gt-*/hq-* session membership",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Version: "0.3.1",
|
Version: "0.3.1",
|
||||||
Date: "2026-01-17",
|
Date: "2026-01-17",
|
||||||
|
|||||||
@@ -237,10 +237,8 @@ func calculateEffectiveTimeout(idleCycles int) (time.Duration, error) {
|
|||||||
// waitForActivitySignal starts bd activity --follow and waits for any output.
|
// waitForActivitySignal starts bd activity --follow and waits for any output.
|
||||||
// Returns immediately when a line is received, or when context is canceled.
|
// Returns immediately when a line is received, or when context is canceled.
|
||||||
func waitForActivitySignal(ctx context.Context, workDir string) (*AwaitSignalResult, error) {
|
func waitForActivitySignal(ctx context.Context, workDir string) (*AwaitSignalResult, error) {
|
||||||
// Start bd activity --follow --since 1s
|
// Start bd activity --follow
|
||||||
// The --since flag ensures we only wait for NEW events, not historical ones.
|
cmd := exec.CommandContext(ctx, "bd", "activity", "--follow")
|
||||||
// Without this, the feed would immediately return old activity and never timeout.
|
|
||||||
cmd := exec.CommandContext(ctx, "bd", "activity", "--follow", "--since", "1s")
|
|
||||||
cmd.Dir = workDir
|
cmd.Dir = workDir
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
|
|||||||
@@ -184,10 +184,9 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
|
|
||||||
// Track per-rig status for LED indicators and sorting
|
// Track per-rig status for LED indicators and sorting
|
||||||
type rigStatus struct {
|
type rigStatus struct {
|
||||||
hasWitness bool
|
hasWitness bool
|
||||||
hasRefinery bool
|
hasRefinery bool
|
||||||
polecatCount int
|
opState string // "OPERATIONAL", "PARKED", or "DOCKED"
|
||||||
opState string // "OPERATIONAL", "PARKED", or "DOCKED"
|
|
||||||
}
|
}
|
||||||
rigStatuses := make(map[string]*rigStatus)
|
rigStatuses := make(map[string]*rigStatus)
|
||||||
|
|
||||||
@@ -202,10 +201,8 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
working int
|
working int
|
||||||
}
|
}
|
||||||
healthByType := map[AgentType]*agentHealth{
|
healthByType := map[AgentType]*agentHealth{
|
||||||
AgentPolecat: {},
|
|
||||||
AgentWitness: {},
|
AgentWitness: {},
|
||||||
AgentRefinery: {},
|
AgentRefinery: {},
|
||||||
AgentDeacon: {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single pass: track rig status AND agent health
|
// Single pass: track rig status AND agent health
|
||||||
@@ -215,7 +212,8 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track rig-level status (witness/refinery/polecat presence)
|
// Track rig-level status (witness/refinery presence)
|
||||||
|
// Polecats are not tracked in tmux - they're a GC concern, not a display concern
|
||||||
if agent.Rig != "" && registeredRigs[agent.Rig] {
|
if agent.Rig != "" && registeredRigs[agent.Rig] {
|
||||||
if rigStatuses[agent.Rig] == nil {
|
if rigStatuses[agent.Rig] == nil {
|
||||||
rigStatuses[agent.Rig] = &rigStatus{}
|
rigStatuses[agent.Rig] = &rigStatus{}
|
||||||
@@ -225,8 +223,6 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
rigStatuses[agent.Rig].hasWitness = true
|
rigStatuses[agent.Rig].hasWitness = true
|
||||||
case AgentRefinery:
|
case AgentRefinery:
|
||||||
rigStatuses[agent.Rig].hasRefinery = true
|
rigStatuses[agent.Rig].hasRefinery = true
|
||||||
case AgentPolecat:
|
|
||||||
rigStatuses[agent.Rig].polecatCount++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,9 +250,10 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
var parts []string
|
var parts []string
|
||||||
|
|
||||||
// Add per-agent-type health in consistent order
|
// Add per-agent-type health in consistent order
|
||||||
// Format: "1/10 😺" = 1 working out of 10 total
|
// Format: "1/3 👁️" = 1 working out of 3 total
|
||||||
// Only show agent types that have sessions
|
// Only show agent types that have sessions
|
||||||
agentOrder := []AgentType{AgentPolecat, AgentWitness, AgentRefinery, AgentDeacon}
|
// Note: Polecats and Deacon excluded - idle state display is misleading noise
|
||||||
|
agentOrder := []AgentType{AgentWitness, AgentRefinery}
|
||||||
var agentParts []string
|
var agentParts []string
|
||||||
for _, agentType := range agentOrder {
|
for _, agentType := range agentOrder {
|
||||||
health := healthByType[agentType]
|
health := healthByType[agentType]
|
||||||
@@ -287,7 +284,7 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
rigs = append(rigs, rigInfo{name: rigName, status: status})
|
rigs = append(rigs, rigInfo{name: rigName, status: status})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by: 1) running state, 2) polecat count (desc), 3) operational state, 4) alphabetical
|
// Sort by: 1) running state, 2) operational state, 3) alphabetical
|
||||||
sort.Slice(rigs, func(i, j int) bool {
|
sort.Slice(rigs, func(i, j int) bool {
|
||||||
isRunningI := rigs[i].status.hasWitness || rigs[i].status.hasRefinery
|
isRunningI := rigs[i].status.hasWitness || rigs[i].status.hasRefinery
|
||||||
isRunningJ := rigs[j].status.hasWitness || rigs[j].status.hasRefinery
|
isRunningJ := rigs[j].status.hasWitness || rigs[j].status.hasRefinery
|
||||||
@@ -297,12 +294,7 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
return isRunningI
|
return isRunningI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Secondary sort: polecat count (descending)
|
// Secondary sort: operational state (for non-running rigs: OPERATIONAL < PARKED < DOCKED)
|
||||||
if rigs[i].status.polecatCount != rigs[j].status.polecatCount {
|
|
||||||
return rigs[i].status.polecatCount > rigs[j].status.polecatCount
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tertiary sort: operational state (for non-running rigs: OPERATIONAL < PARKED < DOCKED)
|
|
||||||
stateOrder := map[string]int{"OPERATIONAL": 0, "PARKED": 1, "DOCKED": 2}
|
stateOrder := map[string]int{"OPERATIONAL": 0, "PARKED": 1, "DOCKED": 2}
|
||||||
stateI := stateOrder[rigs[i].status.opState]
|
stateI := stateOrder[rigs[i].status.opState]
|
||||||
stateJ := stateOrder[rigs[j].status.opState]
|
stateJ := stateOrder[rigs[j].status.opState]
|
||||||
@@ -310,7 +302,7 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
return stateI < stateJ
|
return stateI < stateJ
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quaternary sort: alphabetical
|
// Tertiary sort: alphabetical
|
||||||
return rigs[i].name < rigs[j].name
|
return rigs[i].name < rigs[j].name
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -352,17 +344,12 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show polecat count if > 0
|
|
||||||
// All icons get 1 space, Park gets 2
|
// All icons get 1 space, Park gets 2
|
||||||
space := " "
|
space := " "
|
||||||
if led == "🅿️" {
|
if led == "🅿️" {
|
||||||
space = " "
|
space = " "
|
||||||
}
|
}
|
||||||
display := led + space + rig.name
|
rigParts = append(rigParts, led+space+rig.name)
|
||||||
if status.polecatCount > 0 {
|
|
||||||
display += fmt.Sprintf("(%d)", status.polecatCount)
|
|
||||||
}
|
|
||||||
rigParts = append(rigParts, display)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rigParts) > 0 {
|
if len(rigParts) > 0 {
|
||||||
@@ -421,7 +408,6 @@ func runDeaconStatusLine(t *tmux.Tmux) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rigs := make(map[string]bool)
|
rigs := make(map[string]bool)
|
||||||
polecatCount := 0
|
|
||||||
for _, s := range sessions {
|
for _, s := range sessions {
|
||||||
agent := categorizeSession(s)
|
agent := categorizeSession(s)
|
||||||
if agent == nil {
|
if agent == nil {
|
||||||
@@ -431,16 +417,13 @@ func runDeaconStatusLine(t *tmux.Tmux) error {
|
|||||||
if agent.Rig != "" && registeredRigs[agent.Rig] {
|
if agent.Rig != "" && registeredRigs[agent.Rig] {
|
||||||
rigs[agent.Rig] = true
|
rigs[agent.Rig] = true
|
||||||
}
|
}
|
||||||
if agent.Type == AgentPolecat && registeredRigs[agent.Rig] {
|
|
||||||
polecatCount++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rigCount := len(rigs)
|
rigCount := len(rigs)
|
||||||
|
|
||||||
// Build status
|
// Build status
|
||||||
|
// Note: Polecats excluded - they're ephemeral and idle detection is a GC concern
|
||||||
var parts []string
|
var parts []string
|
||||||
parts = append(parts, fmt.Sprintf("%d rigs", rigCount))
|
parts = append(parts, fmt.Sprintf("%d rigs", rigCount))
|
||||||
parts = append(parts, fmt.Sprintf("%d 😺", polecatCount))
|
|
||||||
|
|
||||||
// Priority 1: Check for hooked work (town beads for deacon)
|
// Priority 1: Check for hooked work (town beads for deacon)
|
||||||
hookedWork := ""
|
hookedWork := ""
|
||||||
@@ -466,7 +449,8 @@ func runDeaconStatusLine(t *tmux.Tmux) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// runWitnessStatusLine outputs status for a witness session.
|
// runWitnessStatusLine outputs status for a witness session.
|
||||||
// Shows: polecat count, crew count, hook or mail preview
|
// Shows: crew count, hook or mail preview
|
||||||
|
// Note: Polecats excluded - they're ephemeral and idle detection is a GC concern
|
||||||
func runWitnessStatusLine(t *tmux.Tmux, rigName string) error {
|
func runWitnessStatusLine(t *tmux.Tmux, rigName string) error {
|
||||||
if rigName == "" {
|
if rigName == "" {
|
||||||
// Try to extract from session name: gt-<rig>-witness
|
// Try to extract from session name: gt-<rig>-witness
|
||||||
@@ -483,25 +467,20 @@ func runWitnessStatusLine(t *tmux.Tmux, rigName string) error {
|
|||||||
townRoot, _ = workspace.Find(paneDir)
|
townRoot, _ = workspace.Find(paneDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count polecats and crew in this rig
|
// Count crew in this rig (crew are persistent, worth tracking)
|
||||||
sessions, err := t.ListSessions()
|
sessions, err := t.ListSessions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil // Silent fail
|
return nil // Silent fail
|
||||||
}
|
}
|
||||||
|
|
||||||
polecatCount := 0
|
|
||||||
crewCount := 0
|
crewCount := 0
|
||||||
for _, s := range sessions {
|
for _, s := range sessions {
|
||||||
agent := categorizeSession(s)
|
agent := categorizeSession(s)
|
||||||
if agent == nil {
|
if agent == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if agent.Rig == rigName {
|
if agent.Rig == rigName && agent.Type == AgentCrew {
|
||||||
if agent.Type == AgentPolecat {
|
crewCount++
|
||||||
polecatCount++
|
|
||||||
} else if agent.Type == AgentCrew {
|
|
||||||
crewCount++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +488,6 @@ func runWitnessStatusLine(t *tmux.Tmux, rigName string) error {
|
|||||||
|
|
||||||
// Build status
|
// Build status
|
||||||
var parts []string
|
var parts []string
|
||||||
parts = append(parts, fmt.Sprintf("%d 😺", polecatCount))
|
|
||||||
if crewCount > 0 {
|
if crewCount > 0 {
|
||||||
parts = append(parts, fmt.Sprintf("%d crew", crewCount))
|
parts = append(parts, fmt.Sprintf("%d crew", crewCount))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
// Version information - set at build time via ldflags
|
// Version information - set at build time via ldflags
|
||||||
var (
|
var (
|
||||||
Version = "0.3.1"
|
Version = "0.4.0"
|
||||||
// Build can be set via ldflags at compile time
|
// Build can be set via ldflags at compile time
|
||||||
Build = "dev"
|
Build = "dev"
|
||||||
// Commit and Branch - the git revision the binary was built from (optional ldflag)
|
// Commit and Branch - the git revision the binary was built from (optional ldflag)
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
description = """
|
|
||||||
Test molecule for verifying exponential backoff behavior.
|
|
||||||
|
|
||||||
Uses SHORT intervals (2s base, 10s max) so you can observe multiple
|
|
||||||
backoff cycles in under a minute.
|
|
||||||
|
|
||||||
Expected backoff progression:
|
|
||||||
- Cycle 0: 2s
|
|
||||||
- Cycle 1: 4s
|
|
||||||
- Cycle 2: 8s
|
|
||||||
- Cycle 3+: 10s (capped)
|
|
||||||
|
|
||||||
Full backoff cycle observable in ~24 seconds.
|
|
||||||
|
|
||||||
## Running This Test
|
|
||||||
|
|
||||||
1. Create a test agent bead (if not exists):
|
|
||||||
```bash
|
|
||||||
bd create --type=agent --title="Backoff Test Agent" --id=hq-backoff-test
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Run the deacon with this formula, or execute steps manually:
|
|
||||||
```bash
|
|
||||||
gt mol step await-signal --agent-bead hq-backoff-test \
|
|
||||||
--backoff-base 2s --backoff-mult 2 --backoff-max 10s
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Watch the idle counter increment on each timeout:
|
|
||||||
```bash
|
|
||||||
bd show hq-backoff-test --json | jq '.[] | .labels'
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Trigger activity to test signal wake:
|
|
||||||
```bash
|
|
||||||
bd create --title="Wake signal" --silent # Any bd command triggers activity
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Reset idle counter after signal (caller responsibility):
|
|
||||||
```bash
|
|
||||||
bd update hq-backoff-test --set-labels=idle:0
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
formula = "mol-backoff-test"
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
[[steps]]
|
|
||||||
id = "heartbeat"
|
|
||||||
title = "Touch heartbeat"
|
|
||||||
description = """
|
|
||||||
Touch heartbeat to show we're alive.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gt deacon heartbeat "backoff test cycle"
|
|
||||||
```
|
|
||||||
|
|
||||||
This updates the deacon's heartbeat file to signal liveness.
|
|
||||||
"""
|
|
||||||
|
|
||||||
[[steps]]
|
|
||||||
id = "await-signal"
|
|
||||||
title = "Wait with exponential backoff (SHORT intervals)"
|
|
||||||
needs = ["heartbeat"]
|
|
||||||
description = """
|
|
||||||
Wait for activity with exponential backoff using TEST intervals.
|
|
||||||
|
|
||||||
**IMPORTANT**: This uses SHORT intervals for testing:
|
|
||||||
- Base: 2s (production: 60s)
|
|
||||||
- Multiplier: 2
|
|
||||||
- Max: 10s (production: 10m)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gt mol step await-signal --agent-bead hq-backoff-test \
|
|
||||||
--backoff-base 2s --backoff-mult 2 --backoff-max 10s
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected behavior:**
|
|
||||||
|
|
||||||
| Idle Cycles | Timeout |
|
|
||||||
|-------------|---------|
|
|
||||||
| 0 | 2s |
|
|
||||||
| 1 | 4s |
|
|
||||||
| 2 | 8s |
|
|
||||||
| 3+ | 10s |
|
|
||||||
|
|
||||||
**On timeout**: The command auto-increments the `idle:N` label on the agent bead.
|
|
||||||
Continue to the next patrol cycle (loop back to heartbeat).
|
|
||||||
|
|
||||||
**On signal**: Activity was detected. Reset the idle counter:
|
|
||||||
```bash
|
|
||||||
bd update hq-backoff-test --set-labels=idle:0
|
|
||||||
```
|
|
||||||
Then loop back to heartbeat for the next cycle.
|
|
||||||
|
|
||||||
**To exit**: When context is high or testing is complete, exit cleanly.
|
|
||||||
"""
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@gastown/gt",
|
"name": "@gastown/gt",
|
||||||
"version": "0.3.0",
|
"version": "0.4.0",
|
||||||
"description": "Gas Town CLI - multi-agent workspace manager with native binary support",
|
"description": "Gas Town CLI - multi-agent workspace manager with native binary support",
|
||||||
"main": "bin/gt.js",
|
"main": "bin/gt.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
Reference in New Issue
Block a user