feat: dynamic auto specialist selection + worker-tier delegation
Build & push image / build-and-push (push) Successful in 33s
Build & push image / build-and-push (push) Successful in 33s
Two Phase-2 swarm upgrades: - auto.go: GADFLY_SPECIALISTS=auto routes the review — a selector model (GADFLY_SELECTOR_MODEL, else the review model) reads the changed files + PR description and picks the smallest relevant lens set from the catalog, and may propose ad-hoc lenses for gaps (e.g. migrations). Structured output via majordomo.Generate[T]; capped + de-duped; falls back to the default suite. - delegate.go: GADFLY_WORKER_MODEL adds a delegate_investigation tool so the reviewer offloads mechanical legwork (trace callers, gather usages) to a cheap worker sub-agent that returns an evidence-cited digest — the top model reasons over summaries, not raw file dumps. Workers get an fs-only toolbox (no sub-delegation). Unset = off. resolveSpecialists now also returns the registry + an auto flag. Docs (README Specialists + config table, CLAUDE.md, main.go header) + tests updated. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7809d1b93d
commit
4b8f9aa39b
@@ -28,7 +28,7 @@ func eq(a, b []string) bool {
|
||||
|
||||
func TestResolveSpecialists_DefaultSuite(t *testing.T) {
|
||||
t.Setenv("GADFLY_SPECIALISTS", "")
|
||||
specs, errs := resolveSpecialists(t.TempDir())
|
||||
specs, _, _, errs := resolveSpecialists(t.TempDir())
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("unexpected errors: %v", errs)
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func TestResolveSpecialists_DefaultSuite(t *testing.T) {
|
||||
|
||||
func TestResolveSpecialists_EnvSelection(t *testing.T) {
|
||||
t.Setenv("GADFLY_SPECIALISTS", "security, tests")
|
||||
specs, errs := resolveSpecialists(t.TempDir())
|
||||
specs, _, _, errs := resolveSpecialists(t.TempDir())
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("unexpected errors: %v", errs)
|
||||
}
|
||||
@@ -48,9 +48,26 @@ func TestResolveSpecialists_EnvSelection(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveSpecialists_AutoFlag(t *testing.T) {
|
||||
t.Setenv("GADFLY_SPECIALISTS", "auto")
|
||||
specs, registry, auto, errs := resolveSpecialists(t.TempDir())
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("unexpected errors: %v", errs)
|
||||
}
|
||||
if !auto {
|
||||
t.Error("expected auto=true for GADFLY_SPECIALISTS=auto")
|
||||
}
|
||||
if specs != nil {
|
||||
t.Errorf("auto mode should return nil specs, got %v", names(specs))
|
||||
}
|
||||
if len(registry) == 0 {
|
||||
t.Error("auto mode should still return the registry catalog")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveSpecialists_UnknownNameErrors(t *testing.T) {
|
||||
t.Setenv("GADFLY_SPECIALISTS", "security,bogus")
|
||||
specs, errs := resolveSpecialists(t.TempDir())
|
||||
specs, _, _, errs := resolveSpecialists(t.TempDir())
|
||||
if len(errs) == 0 {
|
||||
t.Fatal("expected an error for unknown specialist")
|
||||
}
|
||||
@@ -62,7 +79,7 @@ func TestResolveSpecialists_UnknownNameErrors(t *testing.T) {
|
||||
func TestResolveSpecialists_EnvCustomDefinition(t *testing.T) {
|
||||
t.Setenv("GADFLY_SPECIALIST_MIGRATIONS", "Review DB migrations for destructive ops.")
|
||||
t.Setenv("GADFLY_SPECIALISTS", "migrations")
|
||||
specs, errs := resolveSpecialists(t.TempDir())
|
||||
specs, _, _, errs := resolveSpecialists(t.TempDir())
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("unexpected errors: %v", errs)
|
||||
}
|
||||
@@ -83,7 +100,7 @@ define:
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Setenv("GADFLY_SPECIALISTS", "") // let the file drive selection
|
||||
specs, errs := resolveSpecialists(dir)
|
||||
specs, _, _, errs := resolveSpecialists(dir)
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("unexpected errors: %v", errs)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user