-
Notifications
You must be signed in to change notification settings - Fork 40
t2732: Add missing 'name' field to skill frontmatter #2733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,6 +11,7 @@ | |||||||||||||||||||||||||||||||||||||
| # - Secretlint for exposed secrets | ||||||||||||||||||||||||||||||||||||||
| # - Pattern validation (return statements, positional parameters) | ||||||||||||||||||||||||||||||||||||||
| # - Markdown formatting | ||||||||||||||||||||||||||||||||||||||
| # - Skill frontmatter validation (name field matches skill-sources.json) | ||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||
| # For remote auditing (CodeRabbit, Codacy, SonarCloud), use: | ||||||||||||||||||||||||||||||||||||||
| # /code-audit-remote or code-audit-helper.sh | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -620,6 +621,94 @@ check_remote_cli_status() { | |||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||||||||||||||||||
| # Skill Frontmatter Validation | ||||||||||||||||||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||||||||||||||||||
| # Validates that all imported skills registered in skill-sources.json have a | ||||||||||||||||||||||||||||||||||||||
| # 'name' field in their YAML frontmatter matching the registered skill name. | ||||||||||||||||||||||||||||||||||||||
| # This prevents opencode startup errors from missing name fields. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| check_skill_frontmatter() { | ||||||||||||||||||||||||||||||||||||||
| echo -e "${BLUE}Checking Skill Frontmatter...${NC}" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| local skill_sources=".agents/configs/skill-sources.json" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if [[ ! -f "$skill_sources" ]]; then | ||||||||||||||||||||||||||||||||||||||
| print_info "No skill-sources.json found (skipping)" | ||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if ! command -v jq &>/dev/null; then | ||||||||||||||||||||||||||||||||||||||
| print_info "jq not available (skipping skill frontmatter check)" | ||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| local skill_count | ||||||||||||||||||||||||||||||||||||||
| if ! skill_count=$(jq -er ' | ||||||||||||||||||||||||||||||||||||||
| if (.skills | type) == "array" then (.skills | length) | ||||||||||||||||||||||||||||||||||||||
| else error(".skills must be an array") | ||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||
| ' "$skill_sources" 2>/dev/null); then | ||||||||||||||||||||||||||||||||||||||
| print_error "Invalid $skill_sources (cannot parse .skills array)" | ||||||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if [[ "$skill_count" -eq 0 ]]; then | ||||||||||||||||||||||||||||||||||||||
| print_info "No imported skills to validate" | ||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| local errors=0 | ||||||||||||||||||||||||||||||||||||||
| local checked=0 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| local skill_entries | ||||||||||||||||||||||||||||||||||||||
| if ! skill_entries=$(jq -er '.skills[] | "\(.name)|\(.local_path)"' "$skill_sources" 2>/dev/null); then | ||||||||||||||||||||||||||||||||||||||
| print_error "Failed to read skill entries from $skill_sources" | ||||||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| while IFS='|' read -r name local_path; do | ||||||||||||||||||||||||||||||||||||||
| if [[ ! -f "$local_path" ]]; then | ||||||||||||||||||||||||||||||||||||||
| print_warning "Skill file missing: $local_path (skill: $name)" | ||||||||||||||||||||||||||||||||||||||
| ((errors++)) || true | ||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # Extract name from YAML frontmatter (initial block only) | ||||||||||||||||||||||||||||||||||||||
| local fm_name | ||||||||||||||||||||||||||||||||||||||
| fm_name=$(awk ' | ||||||||||||||||||||||||||||||||||||||
| NR == 1 && /^---$/ { in_fm = 1; next } | ||||||||||||||||||||||||||||||||||||||
| in_fm && /^---$/ { exit } | ||||||||||||||||||||||||||||||||||||||
| in_fm && /^[[:space:]]*name:[[:space:]]*/ { | ||||||||||||||||||||||||||||||||||||||
| sub(/^[[:space:]]*name:[[:space:]]*/, "") | ||||||||||||||||||||||||||||||||||||||
| sub(/[[:space:]]+#.*$/, "") | ||||||||||||||||||||||||||||||||||||||
| gsub(/^["'"'"']|["'"'"']$/, "") | ||||||||||||||||||||||||||||||||||||||
| exit | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ' "$local_path") | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+679
to
+689
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if [[ -z "$fm_name" ]]; then | ||||||||||||||||||||||||||||||||||||||
| print_error "Missing 'name' field in frontmatter: $local_path (expected: $name)" | ||||||||||||||||||||||||||||||||||||||
| ((errors++)) || true | ||||||||||||||||||||||||||||||||||||||
| elif [[ "$fm_name" != "$name" ]]; then | ||||||||||||||||||||||||||||||||||||||
| print_error "Name mismatch in $local_path: got '$fm_name', expected '$name'" | ||||||||||||||||||||||||||||||||||||||
| ((errors++)) || true | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ((checked++)) || true | ||||||||||||||||||||||||||||||||||||||
| done <<<"$skill_entries" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if [[ $errors -eq 0 ]]; then | ||||||||||||||||||||||||||||||||||||||
| print_success "Skill frontmatter: $checked skills validated, all have correct 'name' field" | ||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||
| print_error "Skill frontmatter: $errors error(s) in $checked skills" | ||||||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||||||||||||||||||
| # Bundle-Aware Gate Filtering (t1364.6) | ||||||||||||||||||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -731,6 +820,11 @@ main() { | |||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if ! should_skip_gate "skill-frontmatter"; then | ||||||||||||||||||||||||||||||||||||||
| check_skill_frontmatter || exit_code=1 | ||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| check_remote_cli_status | ||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.