Why: the frozen exec port could not express per-request model, tool allowlist, skills, budget, or identifiers, so squad roles and product profiles had no way to steer one execution; contract v0.1.0 semantics (budget/cancel) stayed unconsumed (parity-matrix #4/#10/#16). Evidence: go vet ./... clean; go test ./... all ok, including new loop budget caps (tool calls, prompt tokens, deadline), cancel propagation into a blocking tool, registry Restrict fail-closed policy tests, native adapter v2 tests (model override, allowlist, deadline-bound context, execution-id log header, skills prompt line), and settle classification marking budget_exceeded permanent. Impact: exec.Request gains optional Model/ToolAllowlist/Skills/Budget/ SessionScope/ExecutionID/Env (zero value = legacy behavior); runtime loop enforces a shared budget and emits budget_exceeded events; adapters/native consumes all new fields. Consumers on the old port keep compiling and behaving identically. Refs: docs/parity-matrix.md rows #4/#10/#16 (Batch2 scope); deps/ development-guidelines standards/agent-execution.md (shared budget across retry layers).
38 lines
1.0 KiB
Go
38 lines
1.0 KiB
Go
package exec
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestAssessStepFailureBudgetExceededIsPermanent(t *testing.T) {
|
|
ass := AssessStepFailure(StepFailureSignals{
|
|
Err: errors.New("budget_exceeded: tool calls 12 > max 10"),
|
|
})
|
|
if ass.Class != FailurePermanent {
|
|
t.Fatalf("budget exhaustion must classify permanent (no auto retry), got %s", ass.Class)
|
|
}
|
|
if !strings.Contains(ass.Reason, "permanent") {
|
|
t.Fatalf("want permanent reason, got %s", ass.Reason)
|
|
}
|
|
}
|
|
|
|
func TestAssessStepFailureDeadlinePastIsPermanent(t *testing.T) {
|
|
ass := AssessStepFailure(StepFailureSignals{
|
|
Result: &Result{ErrorReason: "budget_exceeded: deadline 2026-10-01T00:00:00Z passed"},
|
|
})
|
|
if ass.Class != FailurePermanent {
|
|
t.Fatalf("deadline exhaustion must classify permanent, got %s", ass.Class)
|
|
}
|
|
}
|
|
|
|
func TestBudgetZeroValueUnlimited(t *testing.T) {
|
|
var b Budget
|
|
if b.MaxPromptTokens != 0 || b.MaxCompletionTokens != 0 || b.MaxToolCalls != 0 || !b.Deadline.IsZero() {
|
|
t.Fatal("zero budget must express unlimited")
|
|
}
|
|
_ = time.Now
|
|
}
|