diff --git a/.github/ISSUE_TEMPLATE/01-bug-report.yml b/.github/ISSUE_TEMPLATE/01-bug-report.yml new file mode 100644 index 0000000..969e4e1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/01-bug-report.yml @@ -0,0 +1,41 @@ +name: Bug report +description: Report a problem in a skill, reference file, eval fixture, or release artifact. +title: "[Bug]: " +labels: + - bug +body: + - type: dropdown + id: area + attributes: + label: Affected area + options: + - github-profile + - github-repo + - wp-github-actions + - wp-readme-optimizer + - Repository infrastructure + validations: + required: true + - type: textarea + id: summary + attributes: + label: What happened? + description: Describe the current behavior and the expected behavior. + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: Reproduction + description: Include the prompt, relevant files, and steps needed to reproduce. + placeholder: | + 1. Use skill ... + 2. Provide prompt ... + 3. Observe ... + validations: + required: true + - type: textarea + id: context + attributes: + label: Additional context + description: Link to the affected file paths, workflow run, or release asset if applicable. diff --git a/.github/ISSUE_TEMPLATE/02-feature-request.yml b/.github/ISSUE_TEMPLATE/02-feature-request.yml new file mode 100644 index 0000000..af1de0d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02-feature-request.yml @@ -0,0 +1,25 @@ +name: Feature request +description: Propose a new skill, a skill expansion, or repository-level automation improvement. +title: "[Feature]: " +labels: + - enhancement +body: + - type: textarea + id: problem + attributes: + label: What problem should this solve? + description: Describe the user problem or workflow gap. + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed change + description: Describe the skill behavior, references, or templates you want added. + validations: + required: true + - type: textarea + id: evidence + attributes: + label: Supporting material + description: Include source links, example prompts, or related upstream work if relevant. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..c637156 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +# Pull Request Summary + +- What changed? +- Why does it matter? + +## Validation + +- [ ] `bash .github/scripts/validate-skills.sh` +- [ ] Markdown checked locally or in CI +- [ ] Links checked locally or in CI + +## Release Impact + +- [ ] No release impact +- [ ] Existing `.skill` package changes +- [ ] New or renamed skill directory + +## Notes + +Link related issues, upstream references, or follow-up work here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ca79ca5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/scripts/validate-skills.sh b/.github/scripts/validate-skills.sh new file mode 100644 index 0000000..cce46fe --- /dev/null +++ b/.github/scripts/validate-skills.sh @@ -0,0 +1,131 @@ +#!/usr/bin/env bash + +set -euo pipefail + +status=0 + +error() { + local file="$1" + local message="$2" + echo "::error file=${file}::${message}" + status=1 +} + +info() { + local message="$1" + echo "${message}" +} + +extract_frontmatter() { + local skill="$1" + local closing_line + + if [[ "$(head -n 1 "$skill")" != "---" ]]; then + error "$skill" "Missing YAML frontmatter opening delimiter" + return 1 + fi + + closing_line="$(awk 'NR > 1 && /^---$/ { print NR; exit }' "$skill")" + if [[ -z "$closing_line" ]]; then + error "$skill" "Missing YAML frontmatter closing delimiter" + return 1 + fi + + sed -n "2,$((closing_line - 1))p" "$skill" +} + +validate_skill_frontmatter() { + local skill="$1" + local dir + local frontmatter + local required_fields=("name" "description") + + dir="$(dirname "$skill")" + frontmatter="$(extract_frontmatter "$skill")" || return + + for field in "${required_fields[@]}"; do + if ! grep -q "^${field}:" <<<"$frontmatter"; then + error "$skill" "Missing required '${field}' field in frontmatter" + fi + done + + local declared_name + declared_name="$(sed -n 's/^name:[[:space:]]*//p' <<<"$frontmatter" | head -n 1)" + if [[ -n "$declared_name" && "$declared_name" != "$(basename "$dir")" ]]; then + error "$skill" "Frontmatter name '${declared_name}' must match directory name '$(basename "$dir")'" + fi +} + +validate_skill_references() { + local skill="$1" + local dir + + dir="$(dirname "$skill")" + + while IFS= read -r ref; do + [[ -n "$ref" ]] || continue + if [[ ! -e "${dir}/${ref}" ]]; then + error "$skill" "Referenced file '${ref}' does not exist relative to ${dir}" + fi + done < <(grep -oE '(references|evals|test-cases|assets|scripts)/[^` )"]+' "$skill" | sort -u || true) +} + +validate_evals_json() { + local evals_file="$1" + local skill_dir + + skill_dir="$(basename "$(dirname "$(dirname "$evals_file")")")" + + if ! python3 - "$evals_file" "$skill_dir" <<'PY' +import json +import sys +from pathlib import Path + +evals_path = Path(sys.argv[1]) +skill_dir = sys.argv[2] + +try: + data = json.loads(evals_path.read_text()) +except json.JSONDecodeError as exc: + print(f"::error file={evals_path}::Invalid JSON: {exc}") + sys.exit(1) + +skill_name = data.get("skill_name") +if skill_name != skill_dir: + print( + f"::error file={evals_path}::skill_name must match directory name '{skill_dir}', found '{skill_name}'" + ) + sys.exit(1) + +evals = data.get("evals") +if not isinstance(evals, list) or not evals: + print(f"::error file={evals_path}::evals must be a non-empty array") + sys.exit(1) +PY + then + status=1 + fi +} + +main() { + shopt -s nullglob + local skill + + for skill in */SKILL.md; do + validate_skill_frontmatter "$skill" + validate_skill_references "$skill" + + local skill_dir + skill_dir="$(dirname "$skill")" + + if [[ -f "${skill_dir}/evals/evals.json" ]]; then + validate_evals_json "${skill_dir}/evals/evals.json" + fi + + info "Validated ${skill}" + done + + exit "$status" +} + +main "$@" diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml index 73c0fec..0806358 100644 --- a/.github/workflows/link-check.yml +++ b/.github/workflows/link-check.yml @@ -1,6 +1,7 @@ name: Link Check on: + workflow_dispatch: push: branches: [main] paths: ['**/*.md'] diff --git a/.github/workflows/markdown-lint.yml b/.github/workflows/markdown-lint.yml index 71b89a2..8f3d355 100644 --- a/.github/workflows/markdown-lint.yml +++ b/.github/workflows/markdown-lint.yml @@ -1,6 +1,7 @@ name: Markdown Lint on: + workflow_dispatch: push: branches: [main] paths: ['**/*.md'] diff --git a/.github/workflows/validate-skills.yml b/.github/workflows/validate-skills.yml index 6409e01..f3fe5c1 100644 --- a/.github/workflows/validate-skills.yml +++ b/.github/workflows/validate-skills.yml @@ -1,12 +1,28 @@ name: Validate Skills on: + workflow_dispatch: push: branches: [main] - paths: ['**/SKILL.md'] + paths: + - '**/SKILL.md' + - '**/references/**' + - '**/evals/**' + - '**/test-cases/**' + - '.github/scripts/validate-skills.sh' + - '.github/workflows/validate-skills.yml' pull_request: branches: [main] - paths: ['**/SKILL.md'] + paths: + - '**/SKILL.md' + - '**/references/**' + - '**/evals/**' + - '**/test-cases/**' + - '.github/scripts/validate-skills.sh' + - '.github/workflows/validate-skills.yml' + +permissions: + contents: read jobs: validate: @@ -14,34 +30,5 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Check SKILL.md frontmatter - run: | - status=0 - for skill in */SKILL.md; do - dir=$(dirname "$skill") - - # Check for YAML frontmatter delimiters - if ! head -1 "$skill" | grep -q '^---$'; then - echo "::error file=$skill::Missing YAML frontmatter (no opening ---)" - status=1 - continue - fi - - # Extract frontmatter - frontmatter=$(sed -n '1,/^---$/{ /^---$/d; p; }' "$skill" | tail -n +1) - - # Check required fields - if ! echo "$frontmatter" | grep -q '^name:'; then - echo "::error file=$skill::Missing required 'name' field in frontmatter" - status=1 - fi - if ! echo "$frontmatter" | grep -q '^description:'; then - echo "::error file=$skill::Missing required 'description' field in frontmatter" - status=1 - fi - - if [ $status -eq 0 ]; then - echo "✓ $skill" - fi - done - exit $status + - name: Validate skills and bundled fixtures + run: bash .github/scripts/validate-skills.sh diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..1fc939a --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,122 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or + advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email + address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for +moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported through the private reporting path in [SECURITY.md](SECURITY.md) or by +contacting the maintainer directly. All complaints will be reviewed and +investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), +version 2.1, available at +. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..dc4305f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing + +Thanks for contributing to this repository. + +## Scope + +Each top-level skill directory is intended to be a shippable unit. A complete skill may include: + +- `SKILL.md` +- `references/` +- `evals/` +- `test-cases/` +- optional helper files such as `assets/` or `scripts/` + +Keep changes focused. If you are editing a skill, update its supporting references and evals in the same pull request when needed. + +## Local Checks + +Run the repo validator before opening a pull request: + +```bash +bash .github/scripts/validate-skills.sh +``` + +Recommended additional checks: + +```bash +npx markdownlint-cli2 "**/*.md" +lychee --no-progress "./**/*.md" +``` + +If you do not have those tools installed locally, rely on GitHub Actions for final verification. + +## Authoring Rules + +- Keep frontmatter valid YAML with both opening and closing `---` delimiters. +- Match the `name:` field in each `SKILL.md` to the containing directory name. +- Keep referenced files relative to the skill directory and ensure they exist. +- Prefer concrete instructions over generic advice. +- Update eval fixtures when behavior or expected outputs change. + +## Pull Requests + +- Use a short title that describes the behavioral change. +- Explain what changed and why. +- Note any new references, templates, or release implications. +- Include validation results in the pull request description. + +## Releases + +Releases are built from this repository's workflow configuration and publish `.skill` archives for each top-level skill directory. Do not rename skill directories casually because release filenames and validation assume stable names. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..160c1eb --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| --- | --- | +| `main` | Yes | +| Latest tagged release | Yes | +| Older releases | No | + +## Reporting a Vulnerability + +Please use GitHub's private vulnerability reporting for this repository when possible from the repository's Security tab. + +If private reporting is unavailable to you, contact the maintainer privately before disclosing details publicly. + +Do not report security issues in public GitHub issues, pull requests, discussions, or commit messages. + +## What to Include + +- Affected skill or file path +- Clear reproduction steps +- Impact assessment +- Suggested remediation, if you have one + +## Response Expectations + +- Initial acknowledgement: within 5 business days +- Triage update: within 10 business days +- Fix timing: depends on severity and release impact diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..3c3638a --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,22 @@ +# Support + +## Usage Questions + +Use GitHub issues for questions about: + +- choosing the right skill +- improving wording or examples +- missing documentation +- packaging or installation problems with published `.skill` files + +## Bugs + +Open a bug report with reproduction steps, the affected skill path, and the expected behavior. + +## Security Issues + +Do not use public issues for security concerns. Follow [SECURITY.md](SECURITY.md). + +## Feature Requests + +Open a feature request issue and explain the user problem the skill should solve.