Commit Graph
12 Commits
Author SHA1 Message Date
Mahipal 1b3f6b2286 fix: pick up contributors the cached API has not caught up with
GitHub's /contributors endpoint is heavily cached and can lag a merge by up
to a day. dakshverma23's commit from #129 was already linked to their account
- /commits reports it, and the commit API confirms the link - but they were
absent from the contributor wall because /contributors had not refreshed.

update-contributors.py now unions the two endpoints: /contributors for the
authoritative counts and ordering, /commits for anyone linked but not yet
surfaced. Commits authored with an unlinkable email still appear in neither,
which matches what GitHub's own contributor graph shows.

Wall goes from 13 to 14.
2026-08-24 13:12:25 +02:00
Mahipal 3d21b30ec8 ci: keep the contributor wall up to date automatically
The Thanks-to-our-contributors block was hand-maintained and had gone stale:
it listed 8 people where the API reports 13, omitting valorisa (second by
contribution count with 18), Daytona39264, kevglynn, OctoBored and farhan6667.

tools/update-contributors.py regenerates the block between
<!-- contributors:start --> and <!-- contributors:end --> from the GitHub
contributors API, ordered by contribution count, bots excluded, with the
contribution count in each avatar's tooltip. It has a --check mode and
refuses to write an empty wall if the API returns nothing.

.github/workflows/update-contributors.yml runs it on push to main, weekly,
and on demand, committing only when the block actually changes. The weekly
pass exists because the contributors API is cached and can lag a merge by
about a day, so a push-triggered run alone would miss people.

Avatars come from github.com/<login>.png rather than a third-party
contributor-image service. A README image is fetched on every page view, so
an external host would be an uncontrolled dependency in the most-viewed file
in the repository - the same objection raised against the star-history
endpoint swap in #124.
2026-08-24 12:54:30 +02:00
Mahipal 6243c20d6d docs: add SCOPE.md and write down the contribution policy
Several open PRs could not be decided because CONTRIBUTING.md had nothing to
point at: no scope, no self-promotion or affiliation rules, no PR-size
guidance. Declining on an unwritten rule is unfair to contributors, so the
rules go in first.

SCOPE.md (new)
  What a skill is, and what this repository is not: runtimes, engines,
  products and applications belong in their own repositories. Offensive and
  dual-use content is explicitly in scope - the line is defensive framing and
  authorization, not subject matter.

CONTRIBUTING.md
  - one skill per pull request, and why batching stalls good work
  - overlap: while the description backlog is worked down, a new skill that
    overlaps an existing one will usually be asked to extend it instead
  - self-promotion and vendor links: commercial tools are fine, including
    ones with no free tier, but cost must be stated in Prerequisites and
    links must go to documentation rather than signup funnels
  - affiliation disclosure, with the consequence stated: the PR goes on hold
    until it is disclosed, and nothing is closed over it
  - AI-assisted contributions are allowed and must be disclosed; a human must
    have run the commands and takes responsibility
  - review and response, including a 14-day stale window that closes nothing
    permanently
  - subdomain list corrected from 24 entries to the 34 canonical values the
    validator actually accepts, with the 12 accepted aliases named

README.md
  Removed the claim that every PR is reviewed within 48 hours. The oldest
  open PR has been waiting since April. Replaced the stale "most in need"
  counts, which named domains with 2 and 5 skills that actually have 6 and 10.

tools/README.md
  Corrected to match the code: eight required frontmatter fields, not five,
  and PyYAML is now a dependency.
2026-08-23 18:02:38 +02:00
Mahipal a81b233649 ci: add description-quality and collision gates
The description is the only signal an agent sees at discovery time, so
overlapping descriptions cause misrouting. Nothing in CI checked for that.

- tools/lint-descriptions.py enforces name==folder, description <=1024
  chars, terminal punctuation (a truncation canary), a trigger clause, a
  negative trigger, and a 500-line body cap. Pre-existing failures are
  grandfathered in tools/lint-baseline.json so this blocks new debt only;
  the baseline may shrink and never grow.
- tools/detect-collisions.py scores every description pair by TF-IDF
  cosine and ratchets the count of unreviewed near-duplicates. It strips
  negative-trigger clauses before vectorizing: those name the sibling
  skill on purpose, so scoring them would make correct disambiguation
  raise a pair's similarity.
- wire both into validate-skills.yml, along with agentskills conformance,
  an index.json freshness check, and a guard that fails the build if a
  regex frontmatter parser is reintroduced.
- broaden the path filters from tools/validate-skill.py to tools/**, as
  noted when #105 merged.

All five gates verified to fail on deliberately broken input.
2026-08-23 17:15:12 +02:00
Mahipal 796d96c413 fix: replace three hand-rolled YAML parsers with a shared PyYAML loader
index.json shipped 604 of 817 descriptions truncated to their first line.
The cause was the inline regex parser in update-index.yml: it reconstructed
multi-line descriptions only for the YAML block-scalar styles ('>' and '|')
and silently dropped continuation lines for every other style.

A census of the corpus explains the blast radius:

  block scalar   (description: >-)    43
  single-quoted multiline            278
  plain unquoted multiline           496
  single-line                          0

So 774 of 817 skills (94.7%) used a style the parser mishandled. Commit
d56fc0a7 had fixed only the 43 block-scalar files, and CONTRIBUTING.md
recommends that one working style, which is why it stayed hidden.

- add tools/skill_frontmatter.py, the single PyYAML-backed loader
- add tools/generate-index.py so generation is testable outside CI, with
  a --check mode for use as a gate
- delete the hand-rolled parsers from validate-skill.py (98 lines) and
  validate-agentskills.py, routing both through the shared loader
- implement the reserved-word check that agentskills-skill.schema.json
  names validate-agentskills.py as the enforcement point for

Verified by a differential harness against yaml.safe_load ground truth:
index-vs-source mismatches 606 -> 0.
2026-08-23 17:15:12 +02:00
Mahipal 88f408ada3 Correct agentskills.io validator/schema to match the standard
The standard requires only name+description; additional top-level keys are
permitted metadata. Fixes:
- validator no longer counts extra top-level keys as violations (reports them
  as informational only).
- angle-bracket check now ignores YAML block-scalar indicators (`>`, `>-`,
  `|`), which were false-positiving on multi-line descriptions; no skill has
  genuine angle-bracket content.
- schema additionalProperties false -> true to match.

Audit result: 817/817 compliant.
2026-08-02 09:53:50 -07:00
Mahipal 9bd6051d84 Add agentskills.io compliance schema and validator
- tools/agentskills-skill.schema.json: strict JSON Schema for the
  agentskills.io SKILL.md frontmatter standard (name+description required;
  optional license/compatibility/metadata/allowed-tools; no other top-level
  keys).
- tools/validate-agentskills.py: read-only compliance validator (also checks
  name==directory and the no-angle-brackets rule).
2026-08-02 09:32:13 -07:00
mukul975 673da1f3b0 Fix validator: register hardware-firmware-security subdomain, skip .bak dirs
- Add hardware-firmware-security as a canonical subdomain (folding in the
  firmware-analysis/firmware-security aliases). The 4 new hardware/firmware
  skills failed validation because the subdomain was not in the allowed set.
- Skip skills/*.bak/ backup directories in --all mode; they have no SKILL.md
  and were producing 21 false failures.
- Result: validate-skill.py --all now reports 817/817 passing, exit 0.
2026-06-26 16:37:35 +02:00
Homan AnsariandClaude Opus 4.8 5f5edbb30b Fix validator nested-name misparse, unify with CI, add authorized-use banner
Issues found in review:

1. tools/validate-skill.py: parse_frontmatter operated on the stripped line, so
   an indented nested `name:` (under framework-mapping lists, e.g.
   `name: 'Create Fake Materials: Fake Website'`) clobbered the skill's
   top-level `name`. That produced 94 spurious "invalid kebab-case name"
   failures out of 762. Now indented (non-list) key lines are ignored, so only
   top-level keys define frontmatter fields. Result: 762/762 pass.

2. Two divergent validators: the CI workflow had its own weaker inline parser
   (no subdomain/tag/description checks) requiring a different field set than
   tools/validate-skill.py. CI now delegates to tools/validate-skill.py --all
   (single source of truth); REQUIRED_FIELDS aligned to include
   version/author/license. The duplicate-name and stats steps are unchanged.

3. README: added an explicit authorized-&-lawful-use disclaimer next to the
   existing "not affiliated with Anthropic" note, since the library ships
   offensive/dual-use techniques.

No skill content changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 18:09:19 +02:00
Julio César Suástegui efc9598525 fix(validator): address all remaining review feedback from @mukul975
Three issues fixed:

1. Description list check — added elif isinstance(desc, list) branch that
   emits 'Description must be a string value, not a list'. Previously the
   block was silently skipped when YAML returned a list, causing the skill
   to pass without validating the description field.

2. tools/README.md synced — updated description constraint from '20-500
   characters' to 'at least 50 characters (no upper limit)' to match the
   current code (DESCRIPTION_MIN_CHARS=50, no max enforced).

3. --all with wrong CWD now exits 1 — if glob returns no skill dirs,
   the script prints an error and exits with code 1 instead of reporting
   'Total: 0 Passed: 0 Failed: 0' and exiting 0, which would cause CI to
   silently pass while validating nothing.

All 754 skills continue to pass (0 regressions).
2026-04-04 05:34:31 -06:00
Julio César Suástegui 31f745385b fix(validator): address all review feedback from @mukul975
Required changes:
- Error handling: IOError and UnicodeDecodeError already wrapped in
  try/except from previous commit — still present and correct.
- ALLOWED_SUBDOMAINS: synced with actual repo usage (audited all 754
  skills). identity-access-management (34 skills) added; identity-security
  was the placeholder in its place.

New in this commit:
1. Description minimum: raised from 20 → 50 chars to align with other
   repo tooling as requested.
2. Folded scalar support: parse_frontmatter now handles YAML `>-` and `>`
   folded scalars, preventing incorrect parse of multi-line descriptions.
   Added a comment documenting the one remaining edge case (value-less key
   followed by non-list content — treated as no-value, acceptable for
   well-formed SKILL.md files).
3. Canonical subdomain warnings: alias subdomain values (e.g.
   security-operations vs soc-operations) now print a WARN line pointing
   to the canonical form, but are non-blocking. A _SUBDOMAIN_ALIASES dict
   documents canonical/alias pairs explicitly.
4. Description upper limit: removed hard cap — folded scalars legitimately
   produce long strings in existing skills.
5. PR description: removed false mention of type hints (there are none
   in this file).

Validator now passes 754/754 skills in the repo with 0 errors.
2026-04-03 09:51:27 -06:00
Julio César Suástegui b53f3d4991 fix: add error handling for IOError/UnicodeDecodeError + sync ALLOWED_SUBDOMAINS
- Wrap open() call in try/except for IOError and UnicodeDecodeError
  to report clean errors instead of crashing on encoding issues
- Add all subdomains actually used by existing skills in the repo:
  identity-access-management (33 skills), security-operations (28),
  identity-and-access-management, zero-trust, ot-security, purple-team,
  red-team, ai-security, social-engineering-defense, and others
- Remove identity-security as the canonical form is identity-access-management
2026-04-03 09:49:04 -06:00