agent build

This commit is contained in:
2026-08-28 12:21:44 +05:30
parent b6f8655909
commit f7df96c973
138 changed files with 24164 additions and 207 deletions

View File

@@ -0,0 +1,286 @@
package owliver
import (
"testing"
"github.com/krow/krow-backend/go-api/internal/domain"
)
// Highlights — what is worth asking when nothing has been typed.
//
// Everything here is a pure function of a Context written out by hand, so the
// assertions are about the ranking itself rather than about a fixture. The
// database read that produces a real Context is exercised over HTTP, in
// internal/httpserver.
// ids is the intents a result names, in order.
func ids(list []Suggestion) []string {
out := make([]string, len(list))
for i, s := range list {
out[i] = s.Intent
}
return out
}
// has reports whether an intent was offered.
func has(list []Suggestion, intent string) bool {
for _, s := range list {
if s.Intent == intent {
return true
}
}
return false
}
// A workspace with nothing in it is asked nothing.
//
// The alternative — three questions about empty sets — is the padding this
// whole path is supposed to refuse. "You have no positions, would you like to
// know which position has the strongest pipeline?" is worse than silence.
func TestHighlightsOfAnEmptyOrganizationAreEmpty(t *testing.T) {
for _, page := range []string{"positions", "candidates", "control-center", "analytics",
"talent-pool", "hired-history", "krow-forge", "activity"} {
if got := Highlights(page, Context{}, domain.RoleAdmin); len(got) != 0 {
t.Errorf("%s offered %v for an empty organization", page, ids(got))
}
}
}
// The counts decide, and the loudest one leads.
func TestHighlightsRankByTheData(t *testing.T) {
cases := []struct {
name string
page string
ctx Context
wantTop string
}{
{
name: "unfinished drafts dominate a quiet workspace",
page: "positions",
ctx: Context{DraftPositions: 4, ActivePositions: 1},
wantTop: "position-drafts",
},
{
name: "a role nobody applied to outranks the drafts",
page: "positions",
ctx: Context{DraftPositions: 1, ActivePositions: 3, StarvedPositions: 2},
wantTop: "positions-attention",
},
{
// The tier, not the pile. This is the case weight × count gets
// wrong: forty applications outnumber one abandoned role, and the
// abandoned role is still the finding.
name: "one starved role outranks a large pile of everything else",
page: "positions",
ctx: Context{ActivePositions: 9, StarvedPositions: 1, Applications: 40, Unscreened: 22},
wantTop: "positions-attention",
},
{
// And the thing that just happened is heard, however small.
name: "a single unfinished draft is heard over a busy funnel",
page: "positions",
ctx: Context{ActivePositions: 9, DraftPositions: 1, Applications: 40, Unscreened: 22},
wantTop: "position-drafts",
},
{
name: "unscored candidates are the screening gap",
page: "candidates",
ctx: Context{Applications: 12, Unscreened: 9},
wantTop: "screening-gaps",
},
{
name: "a flagged interview is a risk before it is anything else",
page: "candidates",
ctx: Context{Applications: 12, Unscreened: 2, FlaggedRisks: 4},
wantTop: "candidate-risk",
},
{
name: "unverified profiles are the talent pool's gap",
page: "talent-pool",
ctx: Context{Profiles: 20, UnverifiedProfiles: 8},
wantTop: "talent-verification",
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := Highlights(c.page, c.ctx, domain.RoleAdmin)
if len(got) == 0 {
t.Fatalf("%s offered nothing", c.page)
}
if got[0].Intent != c.wantTop {
t.Fatalf("led with %q, want %q (whole list %v)", got[0].Intent, c.wantTop, ids(got))
}
})
}
}
// A comparison needs two things to compare.
//
// "Which position has the strongest pipeline?" is not a question about a
// workspace holding one position: the answer is a table of one row, which is
// the same padding as a question about an empty set.
func TestHighlightsDoNotOfferAComparisonOfOne(t *testing.T) {
one := Highlights("positions", Context{ActivePositions: 1, Applications: 3}, domain.RoleAdmin)
if has(one, "position-strength") {
t.Fatalf("offered a pipeline comparison across one position: %v", ids(one))
}
two := Highlights("positions", Context{ActivePositions: 2, Applications: 3}, domain.RoleAdmin)
if !has(two, "position-strength") {
t.Fatalf("two positions is a comparison and was not offered: %v", ids(two))
}
}
// Never more than three, and never the same reading twice.
func TestHighlightsAreCappedAndDistinct(t *testing.T) {
loud := Context{
ActivePositions: 9, DraftPositions: 7, StarvedPositions: 5, UnderfilledActive: 6,
Applications: 40, Unscreened: 22, Shortlisted: 9, Interviewing: 6, Hired: 11,
FlaggedRisks: 4, Staff: 30, Profiles: 60, UnverifiedProfiles: 25, Courses: 14,
ActivityEvents: 900,
}
for page := range catalogue {
got := Highlights(page, loud, domain.RoleAdmin)
if len(got) > MaxSuggestions {
t.Errorf("%s returned %d, the cap is %d", page, len(got), MaxSuggestions)
}
seen := map[string]bool{}
for _, s := range got {
if seen[s.Intent] {
t.Errorf("%s repeated %q", page, s.Intent)
}
seen[s.Intent] = true
if s.Text == "" || s.Intent == "" {
t.Errorf("%s returned an incomplete suggestion: %+v", page, s)
}
// Nothing was typed, so nothing asked for a rendering.
if s.Capability != "" {
t.Errorf("%s carried a shape nobody asked for: %+v", page, s)
}
}
}
}
// Permission is decided before relevance, exactly as it is in Suggest.
//
// A count cannot promote a reading the caller may not perform: talent's rows
// are narrowed by the policy table, so an org-wide figure is not theirs to be
// told even as a ranking input.
func TestHighlightsRefuseWhatARoleCannotRead(t *testing.T) {
loud := Context{ActivePositions: 9, DraftPositions: 7, Applications: 40, Unscreened: 22,
Staff: 30, Profiles: 60}
for _, page := range []string{"positions", "candidates", "hired-history", "control-center"} {
if got := Highlights(page, loud, domain.RoleTalent); len(got) != 0 {
t.Errorf("%s offered talent %v", page, ids(got))
}
if got := Highlights(page, loud, domain.RoleAdmin); len(got) == 0 {
t.Errorf("%s offered an admin nothing — the assertion above proves nothing", page)
}
}
}
// An unrecognised role is offered nothing, as everywhere else.
func TestHighlightsDenyAnUnknownRole(t *testing.T) {
loud := Context{ActivePositions: 9, Applications: 40, Unscreened: 22}
for _, role := range []domain.Role{"", "root", "superuser", "Admin"} {
if got := Highlights("positions", loud, role); len(got) != 0 {
t.Errorf("role %q was offered %v", role, ids(got))
}
}
}
// A page the catalogue does not hold answers with an empty slice, not nil.
func TestHighlightsOfAnUnknownPageAreAnEmptySlice(t *testing.T) {
loud := Context{ActivePositions: 9, Applications: 40}
for _, page := range []string{"", "nowhere", "POSITIONS", "settings"} {
got := Highlights(page, loud, domain.RoleAdmin)
if got == nil {
t.Fatalf("page %q returned nil, which a client cannot range over", page)
}
if len(got) != 0 {
t.Errorf("page %q returned %v", page, ids(got))
}
}
}
// The same state always produces the same three in the same order.
func TestHighlightsAreDeterministic(t *testing.T) {
ctx := Context{ActivePositions: 5, DraftPositions: 3, StarvedPositions: 2,
Applications: 20, Unscreened: 7, Shortlisted: 4}
first := ids(Highlights("positions", ctx, domain.RoleAdmin))
for range 25 {
again := ids(Highlights("positions", ctx, domain.RoleAdmin))
if len(again) != len(first) {
t.Fatalf("got %v, first run was %v", again, first)
}
for i := range first {
if again[i] != first[i] {
t.Fatalf("got %v, first run was %v", again, first)
}
}
}
}
// Every declared Signal names an intent the catalogue actually holds, and is
// monotonic: more of the thing it counts can never make the reading less
// relevant. A signal that fell as its subject grew would be a sign error, and
// the symptom would be a suggestion that disappears exactly when it matters.
func TestSignalsAreMonotonic(t *testing.T) {
small := Context{
ActivePositions: 2, DraftPositions: 1, StarvedPositions: 1, UnderfilledActive: 1,
Applications: 5, Unscreened: 2, Shortlisted: 1, Interviewing: 1, Hired: 1,
FlaggedRisks: 1, Staff: 2, Profiles: 3, UnverifiedProfiles: 1, Courses: 1,
ActivityEvents: 10,
}
large := Context{
ActivePositions: 20, DraftPositions: 10, StarvedPositions: 10, UnderfilledActive: 10,
Applications: 50, Unscreened: 20, Shortlisted: 10, Interviewing: 10, Hired: 10,
FlaggedRisks: 10, Staff: 20, Profiles: 30, UnverifiedProfiles: 10, Courses: 10,
ActivityEvents: 100,
}
for page, intents := range catalogue {
for _, intent := range intents {
if intent.Signal == nil {
continue
}
lo, hi := intent.Signal(small), intent.Signal(large)
if lo < 0 || hi < 0 {
t.Errorf("%s/%s: a negative signal (%d, %d)", page, intent.ID, lo, hi)
}
if hi < lo {
t.Errorf("%s/%s: signal fell as the workspace grew (%d → %d)", page, intent.ID, lo, hi)
}
}
}
}
// A tier decides before a count does, everywhere.
//
// Stated as a property rather than as a list of pairs, because it is the whole
// design: a signal is "how much does this matter when it is happening at all",
// and a count that could climb into the tier above would make a large
// organization's biggest pile outrank its most urgent finding.
func TestATierAlwaysOutranksACount(t *testing.T) {
for tier := 1; tier <= 9; tier++ {
lowestAbove := when(1, tier+1)
highestWithin := when(maxTiebreak*10, tier) // deliberately over the cap
if highestWithin >= lowestAbove {
t.Fatalf("tier %d saturates into tier %d: %d >= %d",
tier, tier+1, highestWithin, lowestAbove)
}
}
// Nothing happening scores nothing, whatever the tier claims.
for tier := 1; tier <= 9; tier++ {
for _, count := range []int{0, -1, -1000} {
if got := when(count, tier); got != 0 {
t.Fatalf("when(%d, %d) = %d, want 0", count, tier, got)
}
}
}
}