From 42fc2adcd88b39c1b224915122f8a03cd9ec4cb9 Mon Sep 17 00:00:00 2001 From: vikingowl Date: Tue, 7 Apr 2026 02:16:35 +0200 Subject: [PATCH] feat(skill): bundled /batch skill with go:embed --- internal/skill/embed.go | 35 ++++++++++++++++++++++ internal/skill/embed_test.go | 53 ++++++++++++++++++++++++++++++++++ internal/skill/skills/batch.md | 19 ++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 internal/skill/embed.go create mode 100644 internal/skill/embed_test.go create mode 100644 internal/skill/skills/batch.md diff --git a/internal/skill/embed.go b/internal/skill/embed.go new file mode 100644 index 0000000..f13f562 --- /dev/null +++ b/internal/skill/embed.go @@ -0,0 +1,35 @@ +package skill + +import ( + "embed" + "fmt" + "io/fs" +) + +//go:embed skills/*.md +var bundledFS embed.FS + +// BundledSkills parses and returns all skills embedded in the binary. +func BundledSkills() ([]*Skill, error) { + entries, err := fs.ReadDir(bundledFS, "skills") + if err != nil { + return nil, fmt.Errorf("skill: reading bundled skills: %w", err) + } + + skills := make([]*Skill, 0, len(entries)) + for _, entry := range entries { + if entry.IsDir() { + continue + } + data, err := bundledFS.ReadFile("skills/" + entry.Name()) + if err != nil { + return nil, fmt.Errorf("skill: reading bundled file %q: %w", entry.Name(), err) + } + s, err := Parse(data, "bundled") + if err != nil { + return nil, fmt.Errorf("skill: parsing bundled file %q: %w", entry.Name(), err) + } + skills = append(skills, s) + } + return skills, nil +} diff --git a/internal/skill/embed_test.go b/internal/skill/embed_test.go new file mode 100644 index 0000000..6920fb1 --- /dev/null +++ b/internal/skill/embed_test.go @@ -0,0 +1,53 @@ +package skill + +import ( + "testing" +) + +func TestBundledSkills_NotEmpty(t *testing.T) { + skills, err := BundledSkills() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(skills) == 0 { + t.Error("expected at least one bundled skill") + } +} + +func TestBundledSkills_BatchExists(t *testing.T) { + skills, err := BundledSkills() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + var batch *Skill + for _, s := range skills { + if s.Frontmatter.Name == "batch" { + batch = s + break + } + } + if batch == nil { + t.Fatal("batch skill not found in bundled skills") + } + if batch.Frontmatter.Description == "" { + t.Error("batch skill missing description") + } + if batch.Body == "" { + t.Error("batch skill has empty body") + } + if batch.Source != "bundled" { + t.Errorf("batch skill source = %q, want %q", batch.Source, "bundled") + } +} + +func TestBundledSkills_AllParseClean(t *testing.T) { + skills, err := BundledSkills() + if err != nil { + t.Fatalf("BundledSkills() error: %v", err) + } + for _, s := range skills { + if s.Frontmatter.Name == "" { + t.Errorf("bundled skill has empty name: %+v", s) + } + } +} diff --git a/internal/skill/skills/batch.md b/internal/skill/skills/batch.md new file mode 100644 index 0000000..ad9a01b --- /dev/null +++ b/internal/skill/skills/batch.md @@ -0,0 +1,19 @@ +--- +name: batch +description: Decompose work into parallel tasks executed by elfs +whenToUse: When a task can be split into independent parallel sub-tasks with no shared write state +--- +Analyze the user's request and decompose it into independent parallel sub-tasks. + +Rules: +1. Identify which parts of the work can run independently (no shared write state). +2. For each independent unit, write a focused prompt that includes specific file paths. +3. Call spawn_elfs with ALL tasks in a single call — do NOT spawn one elf at a time. +4. Read-only tasks on disjoint files can always parallelize. +5. Write tasks to the same file must be sequenced — group them into one elf. +6. Limit batch size to 5-7 tasks for optimal throughput. +7. After all elfs complete, synthesize their outputs into a coherent response. +8. If any elf failed, report the failure and suggest a retry for that specific sub-task. + +User's request: +{{.Args}}