Skip to content

Commit 01c6eb8

Browse files
docs: add cross-file validation documentation
- Create docs/cross-file-validation.md with: - Skill reference detection patterns - Code block support explanation - Go regex quirk documentation ([^*\n]* vs [^*]*) - Orphan detection workflow - Best practices for wiring skills - Update README.md: - Add Cross-File Validation section - Document supported skill reference formats - Update CLAUDE.md: - Add cross-file validation section - Document the Go regex newline quirk - Reference new docs file
1 parent 3694aa6 commit 01c6eb8

3 files changed

Lines changed: 225 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,23 @@ schemas/ # Root-level CUE schemas (duplicated in internal/cue/sch
7474
| Skill | 500 lines | SKILL.md filename, Quick Reference table |
7575
| Plugin | 5KB | name format, semver version, author.name, required fields |
7676

77+
## Cross-File Validation
78+
79+
**Location**: `internal/cli/crossfile.go`
80+
81+
Detects skill references using `findSkillReferences()`:
82+
83+
```go
84+
// Pattern: ^[^*\n]*\bSkill:\s*([a-z0-9][a-z0-9-]*)
85+
// Key: [^*\n]* prevents matching across newlines
86+
```
87+
88+
**Go Regex Quirk**: Character classes like `[^*]` match newlines by default in Go. Use `[^*\n]` to exclude newlines and prevent greedy cross-line matching.
89+
90+
**Orphan Detection**: `FindOrphanedSkills()` builds a reference graph and reports skills with zero incoming edges as info-level suggestions.
91+
92+
See: `docs/cross-file-validation.md`
93+
7794
## Config
7895

7996
Supports `.cclintrc.json`, `.cclintrc.yaml`, `.cclintrc.yml` in project root. Environment variables with `CCLINT_` prefix also supported.

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,24 @@ cclint --format markdown --output report.md
9898

9999
## What It Checks
100100

101+
### Cross-File Validation
102+
103+
cclint validates references between components:
104+
105+
| Check | Description |
106+
|-------|-------------|
107+
| **Skill existence** | Agents referencing non-existent skills produce errors |
108+
| **Orphan detection** | Skills not referenced by any agent/command show as suggestions |
109+
| **Tool permissions** | Commands using undeclared tools produce warnings |
110+
111+
Skill references are detected in multiple formats:
112+
- `Skill: name` - Plain format (including inside code blocks)
113+
- `**Skill**: name` - Bold format
114+
- `Skill(name)` - Function call format
115+
- `Skills:\n - name` - List format
116+
117+
See [Cross-File Validation](docs/cross-file-validation.md) for technical details.
118+
101119
### Agents
102120

103121
| Type | Check |

docs/cross-file-validation.md

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# Cross-File Validation
2+
3+
How cclint detects and validates references between components.
4+
5+
---
6+
7+
## Overview
8+
9+
cclint performs cross-file validation to ensure components reference each other correctly. This includes:
10+
11+
1. **Skill Reference Validation** - Agents referencing skills that don't exist
12+
2. **Orphan Detection** - Skills not referenced by any agent/command
13+
3. **Tool Validation** - Commands using tools they haven't declared
14+
15+
## Skill Reference Detection
16+
17+
### Patterns Recognized
18+
19+
cclint uses multiple regex patterns to detect skill references in agent files:
20+
21+
| Pattern | Example | Description |
22+
|---------|---------|-------------|
23+
| Plain | `Skill: foo-bar` | Standard skill reference |
24+
| Bold | `**Skill**: foo-bar` | Bold-formatted reference |
25+
| Function | `Skill(foo-bar)` | Tool-call style |
26+
| List | `Skills:\n - foo-bar` | List format |
27+
28+
### Code Block Support
29+
30+
Skill references inside markdown code blocks are fully supported:
31+
32+
```markdown
33+
## Foundation
34+
35+
**MANDATORY: Load skills:**
36+
```
37+
Skill: first-skill # Detected ✓
38+
Skill: second-skill # Detected ✓
39+
Skill: third-skill # Detected ✓
40+
```
41+
```
42+
43+
All three skills are detected and validated.
44+
45+
### Technical Details
46+
47+
The detection uses this regex pattern:
48+
49+
```go
50+
regexp.MustCompile(`(?m)^[^*\n]*\bSkill:\s*([a-z0-9][a-z0-9-]*)`)
51+
```
52+
53+
Key components:
54+
- `(?m)` - Multiline mode, `^` matches start of each line
55+
- `[^*\n]*` - Match any chars except `*` (bold markers) or `\n` (newlines)
56+
- `\bSkill:` - Word boundary followed by "Skill:"
57+
- `([a-z0-9][a-z0-9-]*)` - Capture skill name (lowercase, hyphens)
58+
59+
**Important:** The `\n` exclusion is critical. Without it, Go's regex engine would greedily match across newlines, causing only the last skill in a block to be detected.
60+
61+
## Orphan Detection
62+
63+
### What It Checks
64+
65+
An orphaned skill is one with no incoming references from:
66+
- Commands (via `Task(X-specialist)` delegation)
67+
- Agents (via `Skill:` declarations)
68+
- Other skills (via cross-references)
69+
70+
### Output
71+
72+
Orphaned skills appear as suggestions in verbose mode:
73+
74+
```bash
75+
$ cclint skills --verbose
76+
77+
💡 skills/unused-skill/SKILL.md
78+
💡 Skill 'unused-skill' has no incoming references - consider adding crossrefs
79+
```
80+
81+
### Severity
82+
83+
Orphan detection produces `info`-level suggestions (not errors). Skills may legitimately be:
84+
- New and not yet integrated
85+
- Used for reference/documentation only
86+
- Invoked dynamically by name
87+
88+
## Cross-Reference Tracking
89+
90+
### How It Works
91+
92+
1. **Discovery Phase** - Find all agents, commands, and skills
93+
2. **Reference Extraction** - Parse each file for skill references
94+
3. **Graph Building** - Build a map of which skills are referenced
95+
4. **Orphan Detection** - Find skills with zero incoming edges
96+
97+
### Data Structures
98+
99+
```go
100+
type CrossFileValidator struct {
101+
agents map[string]File // agent-name -> file info
102+
skills map[string]File // skill-name -> file info
103+
commands map[string]File // command-name -> file info
104+
}
105+
```
106+
107+
### Validation Flow
108+
109+
```
110+
Agent File
111+
112+
├─→ findSkillReferences(content)
113+
│ └─→ Returns []string of skill names
114+
115+
└─→ For each skill reference:
116+
└─→ Check if skill exists in skills map
117+
├─→ Yes: Mark skill as referenced
118+
└─→ No: Error: "Skill: X references non-existent skill"
119+
```
120+
121+
## Common Issues
122+
123+
### False Positives (Fixed in v1.1.0)
124+
125+
**Issue:** Only detecting one skill per file when multiple are declared.
126+
127+
**Cause:** The regex `[^*]*` matched newlines in Go, causing greedy matching across lines.
128+
129+
**Fix:** Changed to `[^*\n]*` to prevent matching across newlines.
130+
131+
**Before:** 100 "orphaned" skills (mostly false positives)
132+
**After:** 19 genuinely unwired skills
133+
134+
### Skills in Comments
135+
136+
Skill references in markdown comments are NOT detected:
137+
138+
```markdown
139+
<!-- Skill: hidden-skill --> ← Not detected (inside comment)
140+
```
141+
142+
This is intentional - commented references shouldn't count.
143+
144+
## Best Practices
145+
146+
### Wire Skills to Agents
147+
148+
Every skill should be referenced by at least one agent:
149+
150+
```markdown
151+
## Foundation
152+
153+
**MANDATORY: Load skills based on context:**
154+
```
155+
Skill: primary-skill # Always loaded
156+
Skill: secondary-skill # When applicable
157+
```
158+
```
159+
160+
### Use Consistent Formatting
161+
162+
Prefer the plain `Skill: name` format for clarity:
163+
164+
```markdown
165+
# Good
166+
Skill: my-skill
167+
168+
# Also good (in code blocks)
169+
```
170+
Skill: my-skill
171+
```
172+
173+
# Avoid (harder to read)
174+
**Skill**: my-skill
175+
Skill("my-skill")
176+
```
177+
178+
### Check for Orphans Regularly
179+
180+
Run verbose mode periodically to find unwired skills:
181+
182+
```bash
183+
cclint skills --verbose | grep "no incoming references"
184+
```
185+
186+
## Related Documentation
187+
188+
- [Agent Lint Rules](rules/agents.md) - Agent validation rules
189+
- [Skill Lint Rules](rules/skills.md) - Skill validation rules
190+
- [Quality Scoring](scoring/README.md) - Component scoring system

0 commit comments

Comments
 (0)