feat: vendor add end-to-end with deterministic lockfile v2

- go-git in-process clone, default-branch/tag resolution, optional token auth
- web-tree URL normalization (github/gitlab) with implied discovery root
- discovery of skills/commands/agents/mcp, lenient frontmatter with warnings
- selection: all by default, --include with missing-entry hard errors
- external/<source>/<type>/ materialization preserving exec bits
- lockfile v2: deterministic JSON, pinned url/ref/rev, inventory, warnings
- offline black-box e2e suite against local fixture git repositories
This commit is contained in:
2026-08-22 21:52:30 +02:00
parent 2a6498dae1
commit 2c7200380b
16 changed files with 1648 additions and 2 deletions
+54
View File
@@ -0,0 +1,54 @@
package discovery
import "testing"
func TestParseFrontmatter(t *testing.T) {
cases := []struct {
name string
in string
want Frontmatter
warnLen int
}{
{
name: "complete block",
in: "---\nname: Test Skill\ndescription: does things\ntags: a, b\nrequires: c,d\n---\nbody\n",
want: Frontmatter{Name: "Test Skill", Description: "does things", Tags: []string{"a", "b"}, Requires: []string{"c", "d"}},
},
{
name: "no frontmatter",
in: "# Just a file\nbody\n",
want: Frontmatter{},
},
{
name: "unclosed block",
in: "---\nname: Broken\ndescription: never closed\n",
want: Frontmatter{Name: "Broken", Description: "never closed"},
warnLen: 1,
},
{
name: "line missing colon",
in: "---\nname: X\nbroken line without colon\n---\n",
want: Frontmatter{Name: "X"},
warnLen: 1,
},
{
name: "crlf line endings",
in: "---\r\nname: Win\r\ndescription: windows author\r\n---\r\n",
want: Frontmatter{Name: "Win", Description: "windows author"},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
fm, warnings := ParseFrontmatter([]byte(tc.in))
if fm.Name != tc.want.Name || fm.Description != tc.want.Description {
t.Errorf("got %+v, want %+v", fm, tc.want)
}
if len(fm.Tags) != len(tc.want.Tags) || len(fm.Requires) != len(tc.want.Requires) {
t.Errorf("tags/requires mismatch: got %+v want %+v", fm, tc.want)
}
if len(warnings) != tc.warnLen {
t.Errorf("warnings = %v (len %d), want len %d", warnings, len(warnings), tc.warnLen)
}
})
}
}