support milestone and thrash rotation signals
This commit is contained in:
@@ -19,6 +19,9 @@ type Adapter interface {
|
|||||||
type TurnBoundary interface {
|
type TurnBoundary interface {
|
||||||
AtTurnBoundary(context.Context, Session) (bool, error)
|
AtTurnBoundary(context.Context, Session) (bool, error)
|
||||||
}
|
}
|
||||||
|
type RotationSignal interface {
|
||||||
|
RotationSignal(context.Context, Session) (string, error)
|
||||||
|
}
|
||||||
type CLIAdapter struct {
|
type CLIAdapter struct {
|
||||||
Client *Client
|
Client *Client
|
||||||
Harness string
|
Harness string
|
||||||
@@ -58,6 +61,15 @@ func (a CLIAdapter) AtTurnBoundary(ctx context.Context, s Session) (bool, error)
|
|||||||
}
|
}
|
||||||
return !IsBusy(r.Status), nil
|
return !IsBusy(r.Status), nil
|
||||||
}
|
}
|
||||||
|
func (a CLIAdapter) RotationSignal(ctx context.Context, s Session) (string, error) {
|
||||||
|
var r struct {
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
if err := a.Client.Call(ctx, "pane.rotation_signal", s, &r); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return r.Reason, nil
|
||||||
|
}
|
||||||
func (a CLIAdapter) Occupancy(s Session) (float64, error) {
|
func (a CLIAdapter) Occupancy(s Session) (float64, error) {
|
||||||
if a.Usage == nil {
|
if a.Usage == nil {
|
||||||
return 0, fmt.Errorf("adapter: usage reader required")
|
return 0, fmt.Errorf("adapter: usage reader required")
|
||||||
|
|||||||
@@ -161,8 +161,14 @@ func (c *Coordinator) rotate(ctx context.Context, hard float64) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
reason := "threshold"
|
||||||
|
if signal, ok := a.(herdr.RotationSignal); ok {
|
||||||
|
if r, signalErr := signal.RotationSignal(ctx, session); signalErr == nil && r != "" {
|
||||||
|
reason = r
|
||||||
|
}
|
||||||
|
}
|
||||||
occupancy, err := a.Occupancy(session)
|
occupancy, err := a.Occupancy(session)
|
||||||
if err != nil || occupancy < hard {
|
if err != nil || (occupancy < hard && reason == "threshold") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if boundary, ok := a.(herdr.TurnBoundary); ok {
|
if boundary, ok := a.(herdr.TurnBoundary); ok {
|
||||||
@@ -178,7 +184,7 @@ func (c *Coordinator) rotate(ctx context.Context, hard float64) {
|
|||||||
if ref == "" {
|
if ref == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
b, _ := json.Marshal(map[string]string{"handoff_ref": ref, "reason": "threshold"})
|
b, _ := json.Marshal(map[string]string{"handoff_ref": ref, "reason": reason})
|
||||||
e := domain.Event{ID: domain.NewID(), Type: "TaskReleased", TaskID: taskID, Version: task.Version + 1, Payload: b}
|
e := domain.Event{ID: domain.NewID(), Type: "TaskReleased", TaskID: taskID, Version: task.Version + 1, Payload: b}
|
||||||
if c.Store.Append(e) == nil {
|
if c.Store.Append(e) == nil {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ Configured herdr `quota_limit` values are now wired into router availability usi
|
|||||||
|
|
||||||
Quota/standup scheduling now treats `QuotaReported` and `StandupAdvisory` as global events, adds `/v1/standup` read/request behavior, and emits one daily advisory during the 03:00 UTC safety window. Advisory contents include queued, leased, and blocked tasks.
|
Quota/standup scheduling now treats `QuotaReported` and `StandupAdvisory` as global events, adds `/v1/standup` read/request behavior, and emits one daily advisory during the 03:00 UTC safety window. Advisory contents include queued, leased, and blocked tasks.
|
||||||
|
|
||||||
|
Harness adapters now expose optional `pane.rotation_signal` support for milestone/thrash triggers. The coordinator records the returned trigger reason in the handoff release and still requires a safe turn boundary before releasing.
|
||||||
|
|
||||||
Recommended order:
|
Recommended order:
|
||||||
|
|
||||||
1. Add the orchestration coordinator: lease → worktree → harness session → bootstrap → lifecycle events.
|
1. Add the orchestration coordinator: lease → worktree → harness session → bootstrap → lifecycle events.
|
||||||
|
|||||||
Reference in New Issue
Block a user