P4b: skill noun + contrib/store (SQLite for budget/persona/skill/audit)
executus CI / test (push) Has been cancelled
executus CI / test (push) Has been cancelled
Merges the skill half of the persona/skill pair plus the second nested module. (Squashed onto main from phase-4b-skill; the audit/budget/persona batteries it was stacked on already landed via the P4 merge.) - skill/: clean-redesign Skill noun + LEAN SkillStore (lifecycle/versions/ schedule only) + ToRunnable + Memory default. - contrib/store/: separate go.mod carrying modernc.org/sqlite, so the driver never enters the core go.sum. db.Budget()/Personas()/Skills()/Audit() back all four store seams (JSON-blob + indexed columns; round-trip tested). Includes the verified gadfly #5 fixes (AppendVersion tx+UNIQUE+error, Mark*ScheduledRun atomic json_set, busy_timeout, NaN guard). - CI: builds + tests the nested module and asserts it owns the sqlite driver. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package skill
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSkillToRunnable(t *testing.T) {
|
||||
s := &Skill{
|
||||
ID: "s1", Name: "summarizer", SystemPrompt: "summarize well", ModelTier: "fast",
|
||||
MaxIterations: 4, MaxRuntime: 20 * time.Second, Tools: []string{"summarize", "now"},
|
||||
}
|
||||
r := s.ToRunnable()
|
||||
if r.ID != "s1" || r.ModelTier != "fast" || r.MaxIterations != 4 || len(r.LowLevelTools) != 2 {
|
||||
t.Fatalf("ToRunnable mapping wrong: %+v", r)
|
||||
}
|
||||
// A skill exposes a flat tool list, not a palette.
|
||||
if len(r.SkillPalette) != 0 || len(r.SubAgentPalette) != 0 {
|
||||
t.Errorf("skill should have empty palettes, got %+v", r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoryStoreVisibilityAndVersions(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
m := NewMemory()
|
||||
pub := &Skill{ID: "a", Name: "pub", OwnerID: "o1", Visibility: VisibilityPublic}
|
||||
shared := &Skill{ID: "b", Name: "shr", OwnerID: "o1", Visibility: VisibilityShared, SharedWith: []string{"bob"}}
|
||||
priv := &Skill{ID: "c", Name: "prv", OwnerID: "o1", Visibility: VisibilityPrivate}
|
||||
for _, s := range []*Skill{pub, shared, priv} {
|
||||
if err := m.Save(ctx, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if ps, _ := m.ListPublic(ctx); len(ps) != 1 || ps[0].ID != "a" {
|
||||
t.Errorf("ListPublic = %+v", ps)
|
||||
}
|
||||
if ss, _ := m.ListSharedWith(ctx, "bob"); len(ss) != 1 || ss[0].ID != "b" {
|
||||
t.Errorf("ListSharedWith(bob) = %+v", ss)
|
||||
}
|
||||
if ss, _ := m.ListSharedWith(ctx, "carol"); len(ss) != 0 {
|
||||
t.Errorf("ListSharedWith(carol) should be empty, got %+v", ss)
|
||||
}
|
||||
if all, _ := m.ListByOwner(ctx, "o1"); len(all) != 3 {
|
||||
t.Errorf("ListByOwner = %d, want 3", len(all))
|
||||
}
|
||||
// Versions: newest-first, fetchable by id.
|
||||
m.AppendVersion(ctx, SkillVersion{ID: "v1", SkillID: "a", Version: "1.0.0"})
|
||||
m.AppendVersion(ctx, SkillVersion{ID: "v2", SkillID: "a", Version: "1.1.0"})
|
||||
vs, _ := m.ListVersionsBySkill(ctx, "a", 10)
|
||||
if len(vs) != 2 || vs[0].ID != "v2" {
|
||||
t.Errorf("versions newest-first wrong: %+v", vs)
|
||||
}
|
||||
if got, err := m.GetVersionByID(ctx, "v1"); err != nil || got.Version != "1.0.0" {
|
||||
t.Errorf("GetVersionByID: %v %+v", err, got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user