coordinate rotation at harness turn boundaries

This commit is contained in:
kami
2026-07-26 20:32:01 +04:00
parent 4093bdb683
commit 26011ed33c
3 changed files with 23 additions and 0 deletions
+15
View File
@@ -13,6 +13,12 @@ type Adapter interface {
Kill(context.Context, Session) error
Occupancy(Session) (float64, error)
}
// TurnBoundary is optional so older herdr deployments remain usable. A true
// result means the current harness turn has ended and handoff is safe.
type TurnBoundary interface {
AtTurnBoundary(context.Context, Session) (bool, error)
}
type CLIAdapter struct {
Client *Client
Harness string
@@ -43,6 +49,15 @@ func (a CLIAdapter) Release(ctx context.Context, s Session) (string, error) {
func (a CLIAdapter) Kill(ctx context.Context, s Session) error {
return a.Client.Call(ctx, "pane.kill", s, nil)
}
func (a CLIAdapter) AtTurnBoundary(ctx context.Context, s Session) (bool, error) {
var r struct {
Status string `json:"status"`
}
if err := a.Client.Call(ctx, "pane.status", s, &r); err != nil {
return false, err
}
return !IsBusy(r.Status), nil
}
func (a CLIAdapter) Occupancy(s Session) (float64, error) {
if a.Usage == nil {
return 0, fmt.Errorf("adapter: usage reader required")
+6
View File
@@ -165,6 +165,12 @@ func (c *Coordinator) rotate(ctx context.Context, hard float64) {
if err != nil || occupancy < hard {
continue
}
if boundary, ok := a.(herdr.TurnBoundary); ok {
atBoundary, boundaryErr := boundary.AtTurnBoundary(ctx, session)
if boundaryErr == nil && !atBoundary {
continue
}
}
ref, err := a.Release(ctx, session)
if err != nil {
continue
+2
View File
@@ -67,6 +67,8 @@ Quota reporting now has strict payload validation, and `router.QuotaAvailability
Notification delivery now supports Telegram and ntfy fan-out for completion, failure, block, and approval events, with event cursors, bounded polling, and notify-only surface policy preserved. Configure `ORCHESTRA_TELEGRAM_BOT_TOKEN`/`ORCHESTRA_TELEGRAM_CHAT_ID` or `ORCHESTRA_NTFY_TOPIC` to enable it.
Rotation now honors an optional herdr turn-boundary probe (`pane.status`) before hard-threshold release. Adapters without the optional capability retain occupancy-based fallback behavior.
Recommended order:
1. Add the orchestration coordinator: lease → worktree → harness session → bootstrap → lifecycle events.