Tool runner: the cap's reason fails the call; the test proves the ending; the refused-answer limit keys on the caller's prefix and forgets old entries (issue 1966, review round 1)

Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
This commit is contained in:
2026-11-09 13:59:13 +01:00
parent f3a9cc276e
commit 312e29478e
4 changed files with 73 additions and 27 deletions
+10 -2
View File
@@ -206,6 +206,8 @@ type child struct {
// restart decided — which Stop waits for (novox/hq issue 476).
handled chan struct{}
why error
// endedFor is why the runner itself ended the bundle (a line over the cap); its calls fail with it.
endedFor string
// watches are the state watches this child asked for, stopped when it exits (ADR 0201): a child
// that starts again watches again, as its code runs again.
watches []func()
@@ -351,8 +353,11 @@ func Start(module, entry string, env []string, mesh Bus, logf func(string, ...an
// Never left frozen (issue 1966): a reader that stops while the bundle lives leaves the bundle's
// next write blocked for good. Said, and the bundle ended; the exit path below fails what waits
// on it and starts it again.
logf("[mesh-tools] %s's bundle wrote a line over %d bytes (a tool's answer the bus cannot carry); ending the bundle",
module, maxLine)
reason := fmt.Sprintf("%s's bundle wrote a line over %d bytes (a tool's answer the bus cannot carry)", module, maxLine)
logf("[mesh-tools] %s; ending the bundle", reason)
c.mu.Lock()
c.endedFor = reason
c.mu.Unlock()
_ = cmd.Process.Kill()
break
}
@@ -561,6 +566,9 @@ func Start(module, entry string, env []string, mesh Bus, logf func(string, ...an
}
saidMu.Unlock()
c.mu.Lock()
if c.endedFor != "" {
why = c.endedFor + "; the bundle was ended (" + code + ")"
}
c.why = errors.New(why)
watches := c.watches
c.watches = nil