v0.0.27 e9b466a

skills_test.go RawHistoryFolder

1package skills
2
3import (
4	"os"
5	"path/filepath"
6	"testing"
7)
8
9func TestSplitFrontmatter(t *testing.T) {
10	in := "---\nname: foo\ndescription: bar\n---\nbody text\n"
11	front, body := splitFrontmatter(in)
12	if front != "name: foo\ndescription: bar" {
13		t.Errorf("front = %q", front)
14	}
15	if body != "body text\n" {
16		t.Errorf("body = %q", body)
17	}
18
19	front2, body2 := splitFrontmatter("no frontmatter here")
20	if front2 != "" || body2 != "no frontmatter here" {
21		t.Errorf("expected pass-through, got front=%q body=%q", front2, body2)
22	}
23}
24
25func TestParseFrontmatter(t *testing.T) {
26	front := `name: code-review
27description: "Review a recent change."
28allowed-tools: [read, bash]
29permissions:
30  bash: ["git diff*", "git log*"]
31`
32	s := &Skill{}
33	parseFrontmatter(front, s)
34	if s.Name != "code-review" {
35		t.Errorf("name = %q", s.Name)
36	}
37	if s.Description != "Review a recent change." {
38		t.Errorf("description = %q", s.Description)
39	}
40	if got := s.AllowedTools; len(got) != 2 || got[0] != "read" || got[1] != "bash" {
41		t.Errorf("allowed-tools = %v", got)
42	}
43	if got := s.Permissions["bash"]; len(got) != 2 || got[0] != "git diff*" || got[1] != "git log*" {
44		t.Errorf("permissions[bash] = %v", got)
45	}
46}
47
48func TestDiscoverProjectAndGlobalPriorityAndDedup(t *testing.T) {
49	tmp := t.TempDir()
50	zotHome := filepath.Join(tmp, "home")
51	cwd := filepath.Join(tmp, "proj")
52
53	mk := func(dir, name, desc string) {
54		full := filepath.Join(dir, name)
55		os.MkdirAll(full, 0o755)
56		body := "---\nname: " + name + "\ndescription: " + desc + "\n---\n# " + name + "\n"
57		os.WriteFile(filepath.Join(full, "SKILL.md"), []byte(body), 0o644)
58	}
59
60	// Same skill name in BOTH project and global; project should win.
61	mk(filepath.Join(cwd, ".zot", "skills"), "shared", "project version")
62	mk(filepath.Join(zotHome, "skills"), "shared", "global version")
63	// Unique skill in global only.
64	mk(filepath.Join(zotHome, "skills"), "global-only", "from global")
65
66	skills, errs := Discover(zotHome, cwd, "")
67	if len(errs) > 0 {
68		t.Fatalf("errs: %v", errs)
69	}
70	if len(skills) != 2 {
71		t.Fatalf("expected 2 skills, got %d (%v)", len(skills), skills)
72	}
73	shared := FindByName(skills, "shared")
74	if shared == nil || shared.Description != "project version" {
75		t.Errorf("expected project to win for 'shared', got %v", shared)
76	}
77	if FindByName(skills, "global-only") == nil {
78		t.Errorf("global-only skill missing")
79	}
80}
81
82func TestSystemPromptAddendum(t *testing.T) {
83	skills := []*Skill{
84		{Name: "a", Description: "Do A."},
85		{Name: "b", Description: "Do B."},
86	}
87	out := SystemPromptAddendum(skills)
88	if want := "- a — Do A.\n- b — Do B.\n"; !contains(out, want) {
89		t.Errorf("addendum missing entries:\n%s", out)
90	}
91}
92
93func contains(s, sub string) bool {
94	return len(s) >= len(sub) && (s == sub || (len(sub) > 0 && stringIndex(s, sub) >= 0))
95}
96
97func stringIndex(s, sub string) int {
98	for i := 0; i+len(sub) <= len(s); i++ {
99		if s[i:i+len(sub)] == sub {
100			return i
101		}
102	}
103	return -1
104}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 477

↑↓ moveenter openesc close