// Copyright 2026 Alibaba Group // Licensed under the Apache License, Version 2.0 (the "License"); // // Mono↔multi skill content QA (G1–G5). Spec: docs/skill-mono-multi-qa.md // Contract: skills/content-qa/mono-multi-coverage.yaml package unit_test import ( "bytes" "fmt" "net/url" "os" "path/filepath" "regexp" "sort" "strings" "testing" "gopkg.in/yaml.v3" ) type monoMultiQAContract struct { SchemaVersion int `yaml:"schema_version"` Coverage []struct { Mono string `yaml:"mono"` MultiSkill string `yaml:"multi_skill"` MultiRefs []string `yaml:"multi_refs"` } `yaml:"coverage"` OmitCoverage []struct { Mono string `yaml:"mono"` Disposition string `yaml:"disposition"` Via string `yaml:"via"` Reason string `yaml:"reason"` } `yaml:"omit_coverage"` GlobalProtocols []struct { ID string `yaml:"id"` MultiPath string `yaml:"multi_path"` } `yaml:"global_protocols"` OmitGlobal []struct { ID string `yaml:"id"` Disposition string `yaml:"disposition"` Reason string `yaml:"reason"` ExpectedMulti string `yaml:"expected_multi"` } `yaml:"omit_global"` PairedFiles []struct { Mono string `yaml:"mono"` Multi string `yaml:"multi"` Mode string `yaml:"mode"` LinkSubstitutions []monoMultiLinkSubstitution `yaml:"link_substitutions"` } `yaml:"paired_files"` PairedTrees []struct { Mono string `yaml:"mono"` Multi string `yaml:"multi"` Mode string `yaml:"mode"` } `yaml:"paired_trees"` OrphanScriptsAllowlist []struct { Path string `yaml:"path"` Disposition string `yaml:"disposition"` Reason string `yaml:"reason"` } `yaml:"orphan_scripts_allowlist"` SkillsWithoutReferencesAllowlist []string `yaml:"skills_without_references_allowlist"` } type monoMultiLinkSubstitution struct { Mono string `yaml:"mono"` Multi string `yaml:"multi"` } type markdownLink struct { Line int Target string } type markdownLinkIssue struct { Link markdownLink Resolved string Err error } var inlineMarkdownLinkPattern = regexp.MustCompile(`!?\[[^\]\n]*\]\(\s*(<[^>\n]+>|[^)\s\n]+)(?:\s+[^)\n]+)?\)`) func loadMonoMultiQAContract(t *testing.T) (string, monoMultiQAContract) { t.Helper() root := repoRoot(t) path := filepath.Join(root, "skills", "content-qa", "mono-multi-coverage.yaml") data, err := os.ReadFile(path) if err != nil { t.Fatalf("read contract: %v", err) } var c monoMultiQAContract if err := yaml.Unmarshal(data, &c); err != nil { t.Fatalf("parse contract: %v", err) } if c.SchemaVersion != 1 { t.Fatalf("unsupported schema_version %d", c.SchemaVersion) } return root, c } func TestMonoMultiSkillContentG1Shape(t *testing.T) { root, c := loadMonoMultiQAContract(t) multiRoot := filepath.Join(root, "skills", "multi") entries, err := os.ReadDir(multiRoot) if err != nil { t.Fatal(err) } foundShared := false noRefs := map[string]bool{} for _, name := range c.SkillsWithoutReferencesAllowlist { noRefs[name] = true } for _, e := range entries { if !e.IsDir() { t.Errorf("G1: unexpected non-directory %s under skills/multi", e.Name()) continue } name := e.Name() if !strings.HasPrefix(name, "dingtalk-") { t.Errorf("G1: invalid skill directory name %q (want dingtalk-*)", name) } if name == "dingtalk-shared" { foundShared = true } skillMD := filepath.Join(multiRoot, name, "SKILL.md") if _, err := os.Stat(skillMD); err != nil { t.Errorf("G1: missing SKILL.md for %s: %v", name, err) } refs := filepath.Join(multiRoot, name, "references") if _, err := os.Stat(refs); err != nil && !noRefs[name] { t.Errorf("G1: missing references/ for %s (add dir or skills_without_references_allowlist)", name) } if noRefs[name] { if _, err := os.Stat(refs); err == nil { t.Errorf("G1: %s is on skills_without_references_allowlist but references/ exists; remove allowlist entry", name) } } } if !foundShared { t.Error("G1: skills/multi must contain dingtalk-shared") } } func TestMonoMultiSkillContentG2Frontmatter(t *testing.T) { root, _ := loadMonoMultiQAContract(t) multiRoot := filepath.Join(root, "skills", "multi") entries, err := os.ReadDir(multiRoot) if err != nil { t.Fatal(err) } for _, e := range entries { if !e.IsDir() { continue } name := e.Name() path := filepath.Join(multiRoot, name, "SKILL.md") body, err := os.ReadFile(path) if err != nil { t.Errorf("%s: %v", name, err) continue } fm, err := parseSkillFrontmatter(body) if err != nil { t.Errorf("G2: %s: %v", name, err) continue } if fm.Name != name { t.Errorf("G2: %s: frontmatter name %q != directory", name, fm.Name) } if strings.TrimSpace(fm.Description) == "" { t.Errorf("G2: %s: empty description", name) } category := fm.Metadata.Category if category == "" { t.Errorf("G2: %s: missing metadata.category", name) } else if category != "product" && category != "shared" { t.Errorf("G2: %s: metadata.category %q want product|shared", name, category) } wantCat := "product" if name == "dingtalk-shared" { wantCat = "shared" } if category != "" && category != wantCat { t.Errorf("G2: %s: metadata.category %q want %q", name, category, wantCat) } bins := fm.Metadata.Requires.Bins hasDWS := false for _, b := range bins { if b == "dws" { hasDWS = true break } } if !hasDWS { t.Errorf("G2: %s: metadata.requires.bins must include dws", name) } } } func TestMonoMultiSkillContentG3Coverage(t *testing.T) { root, c := loadMonoMultiQAContract(t) products := filepath.Join(root, "skills", "mono", "references", "products") stems, err := monoProductStems(products) if err != nil { t.Fatal(err) } covered := map[string]bool{} for _, row := range c.Coverage { if row.Mono == "" || row.MultiSkill == "" { t.Fatalf("G3: coverage row missing mono/multi_skill: %+v", row) } if covered[row.Mono] { t.Errorf("G3: duplicate coverage for mono %q", row.Mono) } covered[row.Mono] = true skillDir := filepath.Join(root, "skills", "multi", row.MultiSkill) if _, err := os.Stat(filepath.Join(skillDir, "SKILL.md")); err != nil { t.Errorf("G3: coverage %s → %s missing SKILL.md: %v", row.Mono, row.MultiSkill, err) } for _, rel := range row.MultiRefs { p := filepath.Join(skillDir, filepath.FromSlash(rel)) if _, err := os.Stat(p); err != nil { t.Errorf("G3: coverage %s → %s missing %s: %v", row.Mono, row.MultiSkill, rel, err) } } } omitted := map[string]bool{} for _, row := range c.OmitCoverage { if row.Mono == "" || strings.TrimSpace(row.Reason) == "" || strings.TrimSpace(row.Disposition) == "" { t.Fatalf("G3: omit_coverage requires mono, disposition, reason: %+v", row) } omitted[row.Mono] = true } for stem := range stems { if covered[stem] || omitted[stem] { continue } t.Errorf("G3: mono product stem %q not in coverage or omit_coverage", stem) } for stem := range covered { if !stems[stem] { t.Errorf("G3: coverage mono %q has no matching skills/mono/references/products entry", stem) } } for stem := range omitted { if !stems[stem] { t.Errorf("G3: omit_coverage mono %q has no matching products entry", stem) } } } func TestMonoMultiSkillContentG4Drift(t *testing.T) { root, c := loadMonoMultiQAContract(t) multiRoot := filepath.Join(root, "skills", "multi") for _, g := range c.GlobalProtocols { p := filepath.Join(multiRoot, filepath.FromSlash(g.MultiPath)) if _, err := os.Stat(p); err != nil { t.Errorf("G4: global protocol %s missing at %s: %v", g.ID, g.MultiPath, err) } } for _, o := range c.OmitGlobal { if strings.TrimSpace(o.ID) == "" || strings.TrimSpace(o.Disposition) == "" || strings.TrimSpace(o.Reason) == "" { t.Fatalf("G4: omit_global requires id, disposition, reason: %+v", o) } } for _, pair := range c.PairedFiles { monoPath := filepath.Join(root, "skills", "mono", filepath.FromSlash(pair.Mono)) multiPath := filepath.Join(multiRoot, filepath.FromSlash(pair.Multi)) monoData, err := os.ReadFile(monoPath) if err != nil { t.Errorf("G4: paired mono %s: %v", pair.Mono, err) continue } multiData, err := os.ReadFile(multiPath) if err != nil { t.Errorf("G4: paired multi %s: %v", pair.Multi, err) continue } mode := pair.Mode if mode == "" { mode = "identical" } if err := comparePairedFileContent(monoData, multiData, mode, pair.LinkSubstitutions); err != nil { t.Errorf("G4: paired file mono %s vs multi %s: %v", pair.Mono, pair.Multi, err) } } for _, pair := range c.PairedTrees { if pair.Mono == "" || pair.Multi == "" { t.Fatalf("G4: paired tree requires mono and multi paths: %+v", pair) } mode := pair.Mode if mode == "" { mode = "identical" } if mode != "identical" { t.Errorf("G4: unknown paired tree mode %q", mode) continue } monoDir := filepath.Join(root, "skills", "mono", filepath.FromSlash(pair.Mono)) multiDir := filepath.Join(multiRoot, filepath.FromSlash(pair.Multi)) monoFiles, err := readRelativeFileTree(monoDir) if err != nil { t.Errorf("G4: paired mono tree %s: %v", pair.Mono, err) continue } multiFiles, err := readRelativeFileTree(multiDir) if err != nil { t.Errorf("G4: paired multi tree %s: %v", pair.Multi, err) continue } for rel, monoData := range monoFiles { multiData, ok := multiFiles[rel] if !ok { t.Errorf("G4: paired multi tree %s missing %s from mono %s", pair.Multi, rel, pair.Mono) continue } if !bytes.Equal(monoData, multiData) { t.Errorf("G4: paired tree file differs: mono %s/%s vs multi %s/%s", pair.Mono, rel, pair.Multi, rel) } } for rel := range multiFiles { if _, ok := monoFiles[rel]; !ok { t.Errorf("G4: paired mono tree %s missing %s from multi %s", pair.Mono, rel, pair.Multi) } } } allow := map[string]bool{} for _, row := range c.OrphanScriptsAllowlist { if row.Path == "" || row.Disposition == "" || row.Reason == "" { t.Fatalf("G4: orphan allowlist requires path, disposition, reason: %+v", row) } allow[filepath.ToSlash(row.Path)] = true } var orphans []string entries, err := os.ReadDir(multiRoot) if err != nil { t.Fatal(err) } for _, e := range entries { if !e.IsDir() { continue } skill := e.Name() scriptsDir := filepath.Join(multiRoot, skill, "scripts") if st, err := os.Stat(scriptsDir); err != nil || !st.IsDir() { continue } blob := skillMarkdownBlob(t, filepath.Join(multiRoot, skill)) _ = filepath.WalkDir(scriptsDir, func(path string, d os.DirEntry, walkErr error) error { if walkErr != nil || d.IsDir() { return walkErr } rel, err := filepath.Rel(multiRoot, path) if err != nil { return err } relSlash := filepath.ToSlash(rel) base := filepath.Base(path) if strings.Contains(blob, base) || strings.Contains(blob, relSlash) { return nil } if allow[relSlash] { return nil } orphans = append(orphans, relSlash) return nil }) } for _, o := range orphans { t.Errorf("G4: orphan script %s (reference from skill markdown or add orphan_scripts_allowlist)", o) } for path := range allow { full := filepath.Join(multiRoot, filepath.FromSlash(path)) if _, err := os.Stat(full); err != nil { t.Errorf("G4: orphan allowlist path missing on disk: %s", path) } } } func TestMonoMultiSkillContentG5RelativeLinks(t *testing.T) { root, c := loadMonoMultiQAContract(t) multiRoot := filepath.Join(root, "skills", "multi") sources := map[string]bool{} for _, pair := range c.PairedFiles { if pair.Mono == "" || pair.Multi == "" { t.Fatalf("G5: paired file requires mono and multi paths: %+v", pair) } sources[filepath.Join(root, "skills", "mono", filepath.FromSlash(pair.Mono))] = true sources[filepath.Join(multiRoot, filepath.FromSlash(pair.Multi))] = true } for _, pair := range c.PairedTrees { if pair.Mono == "" || pair.Multi == "" { t.Fatalf("G5: paired tree requires mono and multi paths: %+v", pair) } trees := []string{ filepath.Join(root, "skills", "mono", filepath.FromSlash(pair.Mono)), filepath.Join(multiRoot, filepath.FromSlash(pair.Multi)), } for _, tree := range trees { files, err := readRelativeFileTree(tree) if err != nil { t.Errorf("G5: read paired Markdown tree %s: %v", tree, err) continue } for rel := range files { sources[filepath.Join(tree, filepath.FromSlash(rel))] = true } } } paths := make([]string, 0, len(sources)) for path := range sources { paths = append(paths, path) } sort.Strings(paths) for _, source := range paths { if !strings.EqualFold(filepath.Ext(source), ".md") { continue } data, err := os.ReadFile(source) if err != nil { t.Errorf("G5: read %s: %v", source, err) continue } rel, relErr := filepath.Rel(root, source) if relErr != nil { rel = source } for _, issue := range unresolvedRelativeMarkdownLinks(root, source, data) { resolved := issue.Resolved if resolved != "" { if resolvedRel, err := filepath.Rel(root, resolved); err == nil { resolved = filepath.ToSlash(resolvedRel) } } t.Errorf("G5: %s:%d relative link %q resolves to %q: %v", filepath.ToSlash(rel), issue.Link.Line, issue.Link.Target, resolved, issue.Err) } } } func TestMonoMultiSkillContentLinkNormalization(t *testing.T) { rules := []monoMultiLinkSubstitution{ {Mono: "../url-patterns.md", Multi: "../../dingtalk-shared/references/url-patterns.md"}, {Mono: "../intent-guide.md", Multi: "sheet-intent-guide.md"}, } mono := []byte("url=../url-patterns.md\nintent=../intent-guide.md\n") multi := []byte("url=../../dingtalk-shared/references/url-patterns.md\nintent=sheet-intent-guide.md\n") if err := comparePairedFileContent(mono, multi, "link-normalized", rules); err != nil { t.Fatalf("valid substitutions rejected: %v", err) } if err := comparePairedFileContent(mono, append(multi, []byte("drift\n")...), "link-normalized", rules); err == nil { t.Fatal("unknown content drift must not be normalized away") } if err := comparePairedFileContent(mono, multi, "identical", rules); err == nil { t.Fatal("identical mode must reject link substitutions") } if err := comparePairedFileContent(mono, multi, "unknown", nil); err == nil { t.Fatal("unknown paired-file mode must fail closed") } } func TestMonoMultiSkillContentLinkNormalizationRejectsInvalidRules(t *testing.T) { tests := []struct { name string mono string multi string rules []monoMultiLinkSubstitution }{ {name: "no rules", mono: "m1", multi: "x1"}, {name: "empty mono", mono: "m1", multi: "x1", rules: []monoMultiLinkSubstitution{{Multi: "x1"}}}, {name: "empty multi", mono: "m1", multi: "x1", rules: []monoMultiLinkSubstitution{{Mono: "m1"}}}, {name: "same sides", mono: "m1", multi: "m1", rules: []monoMultiLinkSubstitution{{Mono: "m1", Multi: "m1"}}}, {name: "duplicate mono", mono: "m1", multi: "x1 x2", rules: []monoMultiLinkSubstitution{{Mono: "m1", Multi: "x1"}, {Mono: "m1", Multi: "x2"}}}, {name: "duplicate multi", mono: "m1 m2", multi: "x1", rules: []monoMultiLinkSubstitution{{Mono: "m1", Multi: "x1"}, {Mono: "m2", Multi: "x1"}}}, {name: "overlapping mono", mono: "m1 m", multi: "x1 x2", rules: []monoMultiLinkSubstitution{{Mono: "m", Multi: "x1"}, {Mono: "m1", Multi: "x2"}}}, {name: "missing occurrence", mono: "m1", multi: "x1", rules: []monoMultiLinkSubstitution{{Mono: "m2", Multi: "x1"}}}, {name: "multiple occurrences", mono: "m1 m1", multi: "x1", rules: []monoMultiLinkSubstitution{{Mono: "m1", Multi: "x1"}}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if _, _, err := normalizePairedFileLinks([]byte(tt.mono), []byte(tt.multi), tt.rules); err == nil { t.Fatal("invalid substitution rules must fail closed") } }) } } func TestMonoMultiSkillContentRelativeLinkScanner(t *testing.T) { root := t.TempDir() docs := filepath.Join(root, "docs") if err := os.MkdirAll(filepath.Join(docs, "sheet"), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(docs, "topic.md"), []byte("# Topic\n"), 0o644); err != nil { t.Fatal(err) } body := []byte("[topic](./topic.md#section)\n[directory](./sheet/)\n[external](https://example.com/a)\n[email](mailto:test@example.com)\n[anchor](#section)\n`[inline](missing-inline.md)`\n```text\n[fenced](missing-fenced.md)\n```\n[missing](missing.md)\n[escape](../../escape.md)\n") issues := unresolvedRelativeMarkdownLinks(root, filepath.Join(docs, "source.md"), body) if len(issues) != 2 { t.Fatalf("got %d unresolved links, want 2: %+v", len(issues), issues) } if issues[0].Link.Target != "missing.md" || issues[0].Link.Line != 10 { t.Fatalf("unexpected unresolved link: %+v", issues[0]) } if issues[1].Link.Target != "../../escape.md" || issues[1].Link.Line != 11 || !strings.Contains(issues[1].Err.Error(), "escapes repository") { t.Fatalf("unexpected escaping link: %+v", issues[1]) } } func TestMonoMultiSkillContentReadRelativeFileTreeFiltersNonMarkdown(t *testing.T) { root := t.TempDir() for _, dir := range []string{"nested", ".hidden"} { if err := os.MkdirAll(filepath.Join(root, dir), 0o755); err != nil { t.Fatal(err) } } files := map[string]string{ "guide.md": "visible", "nested/topic.md": "nested", "notes.txt": "ignored", ".DS_Store": "ignored", ".draft.md": "ignored", ".hidden/topic.md": "ignored", "nested/README.MD": "accepted", "nested/.hidden.md": "ignored", } for rel, body := range files { if err := os.WriteFile(filepath.Join(root, filepath.FromSlash(rel)), []byte(body), 0o644); err != nil { t.Fatal(err) } } got, err := readRelativeFileTree(root) if err != nil { t.Fatal(err) } want := []string{"guide.md", "nested/README.MD", "nested/topic.md"} gotNames := make([]string, 0, len(got)) for rel := range got { gotNames = append(gotNames, rel) } sort.Strings(gotNames) if strings.Join(gotNames, "\n") != strings.Join(want, "\n") { t.Fatalf("visible Markdown tree = %v, want %v", gotNames, want) } } func comparePairedFileContent(monoData, multiData []byte, mode string, substitutions []monoMultiLinkSubstitution) error { switch mode { case "identical": if len(substitutions) != 0 { return fmt.Errorf("identical mode does not allow link_substitutions") } if !bytes.Equal(monoData, multiData) { return fmt.Errorf("contents differ") } return nil case "link-normalized": monoNormalized, multiNormalized, err := normalizePairedFileLinks(monoData, multiData, substitutions) if err != nil { return err } if !bytes.Equal(monoNormalized, multiNormalized) { return fmt.Errorf("contents differ after declared link substitutions") } return nil default: return fmt.Errorf("unknown paired mode %q", mode) } } func normalizePairedFileLinks(monoData, multiData []byte, substitutions []monoMultiLinkSubstitution) ([]byte, []byte, error) { if len(substitutions) == 0 { return nil, nil, fmt.Errorf("link-normalized mode requires link_substitutions") } for i, substitution := range substitutions { if substitution.Mono == "" || substitution.Multi == "" { return nil, nil, fmt.Errorf("link_substitutions[%d] requires non-empty mono and multi values", i) } if substitution.Mono == substitution.Multi { return nil, nil, fmt.Errorf("link_substitutions[%d] must describe a layout difference", i) } for j := 0; j < i; j++ { previous := substitutions[j] if strings.Contains(substitution.Mono, previous.Mono) || strings.Contains(previous.Mono, substitution.Mono) { return nil, nil, fmt.Errorf("link_substitutions[%d].mono overlaps link_substitutions[%d].mono", i, j) } if strings.Contains(substitution.Multi, previous.Multi) || strings.Contains(previous.Multi, substitution.Multi) { return nil, nil, fmt.Errorf("link_substitutions[%d].multi overlaps link_substitutions[%d].multi", i, j) } } if count := bytes.Count(monoData, []byte(substitution.Mono)); count != 1 { return nil, nil, fmt.Errorf("link_substitutions[%d].mono occurs %d times, want exactly 1", i, count) } if count := bytes.Count(multiData, []byte(substitution.Multi)); count != 1 { return nil, nil, fmt.Errorf("link_substitutions[%d].multi occurs %d times, want exactly 1", i, count) } } monoNormalized := bytes.Clone(monoData) multiNormalized := bytes.Clone(multiData) for i, substitution := range substitutions { marker := []byte(fmt.Sprintf("\x00DWS_LINK_SUBSTITUTION_%d\x00", i)) if bytes.Contains(monoNormalized, marker) || bytes.Contains(multiNormalized, marker) { return nil, nil, fmt.Errorf("link_substitutions[%d] normalization marker already exists in content", i) } monoNormalized = bytes.Replace(monoNormalized, []byte(substitution.Mono), marker, 1) multiNormalized = bytes.Replace(multiNormalized, []byte(substitution.Multi), marker, 1) } return monoNormalized, multiNormalized, nil } func unresolvedRelativeMarkdownLinks(repoRoot, source string, body []byte) []markdownLinkIssue { var issues []markdownLinkIssue for _, link := range extractMarkdownLinks(body) { targetPath, check, err := relativeMarkdownTargetPath(link.Target) if err != nil { issues = append(issues, markdownLinkIssue{Link: link, Err: err}) continue } if !check { continue } resolved := filepath.Clean(filepath.Join(filepath.Dir(source), filepath.FromSlash(targetPath))) rel, err := filepath.Rel(repoRoot, resolved) if err != nil { issues = append(issues, markdownLinkIssue{Link: link, Resolved: resolved, Err: err}) continue } if rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { issues = append(issues, markdownLinkIssue{Link: link, Resolved: resolved, Err: fmt.Errorf("target escapes repository")}) continue } if _, err := os.Stat(resolved); err != nil { issues = append(issues, markdownLinkIssue{Link: link, Resolved: resolved, Err: err}) continue } realRoot, err := filepath.EvalSymlinks(repoRoot) if err != nil { issues = append(issues, markdownLinkIssue{Link: link, Resolved: resolved, Err: fmt.Errorf("resolve repository path: %w", err)}) continue } realTarget, err := filepath.EvalSymlinks(resolved) if err != nil { issues = append(issues, markdownLinkIssue{Link: link, Resolved: resolved, Err: fmt.Errorf("resolve target path: %w", err)}) continue } realRel, err := filepath.Rel(realRoot, realTarget) if err != nil || realRel == ".." || strings.HasPrefix(realRel, ".."+string(os.PathSeparator)) { if err == nil { err = fmt.Errorf("target escapes repository through a symbolic link") } issues = append(issues, markdownLinkIssue{Link: link, Resolved: resolved, Err: err}) } } return issues } func extractMarkdownLinks(body []byte) []markdownLink { var links []markdownLink var fence byte for i, line := range strings.Split(string(body), "\n") { if marker := markdownFenceMarker(line); marker != 0 { if fence == 0 { fence = marker } else if fence == marker { fence = 0 } continue } if fence != 0 { continue } masked := maskInlineMarkdownCode(line) for _, match := range inlineMarkdownLinkPattern.FindAllStringSubmatch(masked, -1) { target := match[1] if strings.HasPrefix(target, "<") && strings.HasSuffix(target, ">") { target = strings.TrimSuffix(strings.TrimPrefix(target, "<"), ">") } links = append(links, markdownLink{Line: i + 1, Target: target}) } } return links } func markdownFenceMarker(line string) byte { trimmed := strings.TrimLeft(line, " \t") if strings.HasPrefix(trimmed, "```") { return '`' } if strings.HasPrefix(trimmed, "~~~") { return '~' } return 0 } func maskInlineMarkdownCode(line string) string { masked := []byte(line) for i := 0; i < len(masked); { if masked[i] != '`' { i++ continue } endOfOpener := i for endOfOpener < len(masked) && masked[endOfOpener] == '`' { endOfOpener++ } marker := masked[i:endOfOpener] closingOffset := bytes.Index(masked[endOfOpener:], marker) if closingOffset < 0 { i = endOfOpener continue } end := endOfOpener + closingOffset + len(marker) for j := i; j < end; j++ { masked[j] = ' ' } i = end } return string(masked) } func relativeMarkdownTargetPath(target string) (string, bool, error) { parsed, err := url.Parse(target) if err != nil { return "", false, fmt.Errorf("parse target: %w", err) } if parsed.Scheme != "" || parsed.Host != "" || strings.HasPrefix(target, "//") || strings.HasPrefix(parsed.Path, "/") { return "", false, nil } if parsed.Path == "" { return "", false, nil } path, err := url.PathUnescape(parsed.Path) if err != nil { return "", false, fmt.Errorf("decode target path: %w", err) } return path, true, nil } func readRelativeFileTree(root string) (map[string][]byte, error) { files := map[string][]byte{} err := filepath.WalkDir(root, func(path string, entry os.DirEntry, walkErr error) error { if walkErr != nil { return walkErr } if entry.IsDir() { if path != root && strings.HasPrefix(entry.Name(), ".") { return filepath.SkipDir } return nil } if strings.HasPrefix(entry.Name(), ".") || !strings.EqualFold(filepath.Ext(entry.Name()), ".md") { return nil } rel, err := filepath.Rel(root, path) if err != nil { return err } data, err := os.ReadFile(path) if err != nil { return err } files[filepath.ToSlash(rel)] = data return nil }) return files, err } type skillFrontmatter struct { Name string `yaml:"name"` Description string `yaml:"description"` Metadata struct { Category string `yaml:"category"` Requires struct { Bins []string `yaml:"bins"` } `yaml:"requires"` } `yaml:"metadata"` } func parseSkillFrontmatter(body []byte) (skillFrontmatter, error) { var out skillFrontmatter s := string(body) if !strings.HasPrefix(s, "---\n") && !strings.HasPrefix(s, "---\r\n") { return out, fmt.Errorf("missing YAML frontmatter opener") } rest := s[3:] if strings.HasPrefix(rest, "\r\n") { rest = rest[2:] } else if strings.HasPrefix(rest, "\n") { rest = rest[1:] } end := strings.Index(rest, "\n---") if end < 0 { return out, fmt.Errorf("missing YAML frontmatter closer") } block := rest[:end] if err := yaml.Unmarshal([]byte(block), &out); err != nil { return out, err } return out, nil } func monoProductStems(productsDir string) (map[string]bool, error) { entries, err := os.ReadDir(productsDir) if err != nil { return nil, err } stems := map[string]bool{} for _, e := range entries { name := e.Name() if e.IsDir() { stems[name] = true continue } if strings.HasSuffix(name, ".md") { stems[strings.TrimSuffix(name, ".md")] = true } } return stems, nil } func skillMarkdownBlob(t *testing.T, skillDir string) string { t.Helper() var b strings.Builder _ = filepath.WalkDir(skillDir, func(path string, d os.DirEntry, err error) error { if err != nil || d.IsDir() { return err } if filepath.Ext(path) != ".md" { return nil } data, err := os.ReadFile(path) if err != nil { return err } b.Write(data) b.WriteByte('\n') return nil }) return b.String() }