Commit Graph

94 Commits

Author SHA1 Message Date
Moshe Abramovitch e6526d7c9c fix(benchmarks): capture v3 provenance and block silent field loss
SkillEvaluator's report format changed in July 2026. It stopped emitting
`NVSkills-Eval profile` and `Pass threshold`, both of which the aggregator
reads, so those columns in benchmarks.json have been emptying one skill at a
time as each is re-evaluated: 0% null through June, 57% in July, 100% for
every skill evaluated in August. Nothing failed. The regeneration succeeded,
the schema stayed valid, --check passed, and the data quietly degraded for
six weeks before anyone noticed.

Neither field is recoverable from a v3 report. `profile` is gone entirely.
The only "50%" left is a glossary sentence that is byte-identical across
skills with 4, 5 and 18 tasks, so it is template prose rather than a
measurement — scraping it would stamp an unverified pass threshold on every
skill in the file whose purpose is recording provenance. Both stay null until
SkillEvaluator emits them as real fields; a NO_FABRICATION note records why.

What v3 does add is stronger provenance the parser was discarding:

  - evaluator_version   which build produced the score
  - dataset_digest      sha256 of the exact task set, unique per skill
  - validation_status   pipeline outcome for the run

Capturing these follows the existing multi-pattern idiom already used for
`tasks`, so v1/v2 reports are unaffected and simply leave them null.

The generic fix is null_rate_regressions(), which compares a regeneration
against the committed benchmarks.json and refuses to write when any field
lost values, counting only skills present in both so new additions cannot
false-fire. --allow-null-regressions lands a deliberate retirement without
requiring a code edit under pressure. Verified against the real catalog: it
does not fire today, it does fire when the July drift is replayed over 20
reports, and it flags the exact fields lost in PR #466.

Adds the first tests for .github/scripts (16 cases, two real BENCHMARK.md
fixtures, one per format). Confirmed no regression: every pre-existing field
is byte-identical across all 341 skills.

Also adds the SPDX header aggregate_benchmarks.py was missing; it was the
only .py in .github/scripts/ without one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-20 11:36:31 -05:00
mosheabr 04bc65e172 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-20 11:26:58 -05:00
mosheabr 20bb6aaea8 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-17 09:14:50 -05:00
Nick Goncharenko 8a10fc9393 chore: refresh skill metadata indexes
Signed-off-by: Nick Goncharenko <ngoncharenko@nvidia.com>
2026-08-13 17:33:43 -05:00
Nick Goncharenko 5cc58668d6 chore: drop generated catalog artifacts
Signed-off-by: Nick Goncharenko <ngoncharenko@nvidia.com>
2026-08-13 17:33:43 -05:00
Nick Goncharenko ef8d36f4b0 chore: sync with main
Signed-off-by: Nick Goncharenko <ngoncharenko@nvidia.com>
2026-08-13 17:33:43 -05:00
mosheabr 95814f502f chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-13 14:32:37 -05:00
Moshe Abramovitch 975b6f9af2 test(metadata): stop conflating drift with the warning gate
The --no-ai case asserted on main()'s bare exit code. --check returns 1
for output drift as well as for skill warnings, so any PR that edits
skill content failed this test for reasons unrelated to enrichment.
PR #445 is the first to hit it: 70 changed files including SKILL.md at
62+/147-, which legitimately drifts the checked-in metadata.

Neutralise diff_text for the duration of the run so the exit code is
attributable to the warning gate alone. Drift is already covered by
case 4.

A first attempt simply excused drift with 'rc == 0 or drifted'. That was
worse than the original bug: removing the --no-ai gate entirely still
passed, because drift was present. Mutation-checked properly this time.

Verified against PR #445's content: reproduces the failure without this
change, passes with it, and still fails when the --no-ai gate is removed
-- on both #445's tree and a clean one.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-12 15:37:05 -05:00
mosheabr f926add097 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-12 15:33:52 -05:00
mosheabr dca6a74184 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-12 08:39:50 -05:00
mosheabr bd3208d887 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-11 11:35:33 -04:00
mosheabr 053f17aaf4 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-07 00:00:23 -05:00
mosheabr 550b699aac chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-06 20:51:33 -05:00
Moshe Abramovitch 276b9bcce5 fix(metadata): do not fail --no-ai runs on unenriched new skills
The previous commit made any unbuilt skill non-zero in both modes. That
is wrong for --no-ai: PR CI runs without an inference key by design, so
every newly synced skill arrives there unenriched and would red-line all
open PRs until the regenerate job ran. Caught by CI on this branch --
three freshly synced hsb-ip skills failed the check step.

Gate the non-zero exit on AI being available. Warnings still print in
both modes; a skill that cannot be enriched WITH AI available still
fails. Adds test cases pinning both halves so neither can regress.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-06 12:41:52 -05:00
Moshe Abramovitch 6b919f2a8d test(metadata): cover generator failure handling; fix stale warnings key
The recovery and reporting paths only execute when a skill cannot be
built, so a healthy catalog never exercises them and a regression stays
invisible until it drops a skill from the published catalog.

- add test_generate_skill_metadata.py: induces enrichment failures against
  a stub inference API, no network, nothing written to the repo. Covers
  amendment-failure-keeps-entry, amendment-success, unbuildable-new-skill
  omitted-and-warned, and unbuildable-published-skill recovered
  byte-identically. Fixtures are selected from real metadata.json entries
  at runtime so a rename or retirement does not break them.
- wire it into the PR check job, ahead of the byte-stability check.
- the issue-body script still read warnings.omitted_skills, which the key
  rename left dangling; it would have silently reported zero affected
  skills on every partial run. Read stale_skills, and correct the copy:
  recovered skills are stale, not excluded.

Mutation-checked: disabling recovery fails 3 assertions, routing
amendment failures back into skill_warnings fails 2.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-06 12:41:52 -05:00
Moshe Abramovitch a71659df8b fix(metadata): keep the non-zero exit when a skill has no usable entry
Moving the warning block above the --check early return dropped its
return 1, so a run that omitted a skill would have exited 0. Set the
code once and return it from both the --check and write paths: outputs
are still written so the catalog does not lose a skill, but CI cannot
read a partial success as a pass.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-06 12:41:52 -05:00
Moshe Abramovitch 4d948a7b55 fix(metadata): recover last-good entries; surface enrichment failures honestly
Addresses review feedback on #408.

- workflow: set -o pipefail. Piping the generator into tee reported tee's
  exit status, so a failing generator was read as rc=0 and the failure
  path never ran. This is what let the original silent drop through CI.
- generator: when a skill cannot be rebuilt, reuse its last-good entry
  from the checked-in metadata.json (schema-validated first) instead of
  dropping it. Only entries with no valid prior are omitted, and those
  are the only ones that fail the run.
- generator: an amendment failure on an already-complete entry is no
  longer reported as an omission. The entry ships unchanged with its
  existing values, so it is recorded as a retained notice, not a warning.
- generator: print retained notices and stale-skill warnings before the
  --check early return, so PR CI surfaces them too.
- rename the warnings JSON key omitted_skills -> stale_skills to match
  what the entries now mean.

Verified with an induced-failure harness driving a stub inference API:
11/11 assertions pass (entry kept + values preserved on amendment
failure; byte-identical recovery from baseline; genuinely-new unbuildable
skill still omitted and still fails the run; published skill unbuildable
-> catalog written, not delisted, failure surfaced).

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-06 12:41:52 -05:00
Moshe Abramovitch 941cb0ee7f fix(metadata): never drop a skill when AI enrichment fails
A skill classified materially_changed is sent back to the AI client to see
whether its existing metadata values should be amended. Every required
field already holds a valid value at that point, so the amendment is
optional — but an EnrichmentError returned None, dropping the skill from
metadata.json and skills.sh.json entirely.

The generator does report this, printing a PARTIAL SUCCESS block naming the
skill. What it does not do is stop: it exits 0, writes the reduced file, and
the regeneration PR opens as normal. The output is schema-valid and
internally consistent, so --check passes and the round-trip validation is
handed the missing path as skipped_paths.

This happened on 2026-08-03 to cuopt-multi-objective-exploration, legitimately
materially_changed after the 15:04 sync. The enrichment call returned HTTP 403
three minutes after the identical call had succeeded; 403 was not in the
retryable set, so it was terminal. Run 30842167516 emitted 323 skills, run
30842382996 emitted 322 and opened a PR deleting the entry.

Three changes:

- On enrichment failure in the amendment path, keep the existing metadata and
  record a warning instead of returning None.
- Fail the run if a discovered skill produces no entry, when that skill was in
  the previous metadata.json or when AI enrichment was available. Skills
  dropped via metadata-exclusions.yaml never reach this point. Because the
  workflow opens its validation issue on a non-zero exit, this also gives the
  case an issue without new wiring.
- Retry 403 alongside 429 and 5xx. The gateway returns 403 for transient edge
  rejections as well as real permission failures; retrying costs ~7s on a
  genuine failure and saves an enrichment on a transient one.

Verified against the real catalog with a stubbed API, main vs this branch:

  403 then 200          before: terminal after 1 call
                        after:  recovered on call 2, 5 fields returned
  persistent 403        before: 1 call, no "attempts" in message
                        after:  4 calls, terminal, message cites attempts
  amend-path failure    before: entry dropped
                        after:  entry kept, 5 metadata fields intact
  forced drop, write    before: "updated (322 skills)", exit 0
                        after:  VALIDATION FAILED naming the skill, exit 1

Normal run unchanged: metadata.json unchanged (323 skills), both drift gates
exit 0.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-06 12:41:52 -05:00
mosheabr 9d2bdefc27 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-05 10:58:02 -05:00
Moshe Abramovitch e2baf97468 chore: regenerate metadata after the ±0 uplift fix
Two corrections, neither of which had been reflected in the generated
files:

metadata.json picks up the cuopt-multi-objective-exploration description
reworded in the 8/3 re-sign.

benchmarks.json is regenerated against 937d0e3, which made "±0 points"
parse as 0.0 rather than None. Dimensions with no change had been
dropped from the average-uplift denominator, so every skill carrying a
v2 report was reporting an inflated figure. Six skills move, all
downward and all more accurate:

  nemo-automodel-distributed-training  40.88 -> 32.7
  nemo-relay-plugin-observability      38.0  -> 34.2
  nemo-relay-get-started               36.89 -> 33.2
  nemo-relay-debug-runtime-integration 30.0  -> 24.0
  cuopt-multi-objective-exploration    29.3  -> 28.2
  portfolio-optimization               19.0  -> 17.1

Skill count and row count are unchanged at 323 and 3000.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 13:50:56 -05:00
Moshe Abramovitch 937d0e31f1 fix(benchmarks): count ±0 uplift as zero, not missing
v2 evaluation reports write an unchanged dimension as "±0 points". The
uplift capture in CELL/CELL_V2 accepted only + and -, so those cells fell
through as None. average_uplift() skips None entries, so the row dropped
out of the denominator rather than counting as zero — inflating the
published average for any skill that scored the same with and without the
skill applied.

Accept ± in both cell patterns and route the captures through
parse_uplift(), which normalises ±0 to 0.0.

Re-running the aggregator over all 323 skills corrects six averages, all
downward, and clears every null uplift row (7 -> 0 of 3000):

  nemo-automodel-distributed-training   40.88 -> 32.7
  nemo-relay-plugin-observability        38.0 -> 34.2
  nemo-relay-get-started                36.89 -> 33.2
  nemo-relay-debug-runtime-integration   30.0 -> 24.0
  cuopt-multi-objective-exploration      29.3 -> 28.2
  portfolio-optimization                 19.0 -> 17.1

No other skill's figures change. benchmarks.json is left to the generator
workflow to regenerate.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-08-03 13:38:27 -05:00
Moshe Abramovitch c93c8ee2ff fix(benchmarks): parse both v1 and v2 BENCHMARK.md report formats
SkillEvaluator 0.9.x emits a redesigned BENCHMARK.md. The aggregator was
written against the older layout, so every re-signed skill silently lost
its evaluation data in benchmarks.json: has_results went false, with null
tasks, no agents and no uplift, even though the underlying report carried
richer results than before.

Both layouts are now accepted, since the catalog will hold a mix until
every skill has been re-signed:

- Evaluation Summary (v1) and Evaluation Metadata (v2) field lists
- "Agents Used" bullets (v1) and the inline "- Agents:" line (v2)
- "## Results" and "## Results at a Glance" tables, keyed on either
  Dimension or Measure
- v1 cells ("100% (+70%)") and v2 cells ("45% -> 98% (+53 points)"),
  recording the skill-assisted score in both so the series stays
  comparable
- agent names normalised, so v2's "Claude Code (`provider/model`)" and
  v1's `claude-code` aggregate as one agent

Also fixes a verdict misread. In v2 the real verdict is a callout above
the report body, and the old pattern instead matched the methodology
bullet "- Overall verdict: PASS only when every configured dimension
passes...", which appears in every v2 report. Any failing v2 skill would
have been recorded as PASS. The v1 pattern is now anchored to
end-of-line, and the v2 callout is matched explicitly.

Effect on the current catalog: 5 skills regain results (skills without
results 27 -> 22) and result rows go 2955 -> 3000. Only the 7 skills
already carrying v2 reports change; v1 records are untouched.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 10:50:51 -05:00
mosheabr 0122ea0afa chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-08-01 16:18:38 -05:00
Ramakrishna Prabhu cef19a5b18 refactor: rename component file and regenerate catalog metadata
- Rename components.d/cufolio.yml → components.d/portfolio-optimization.yml
  (filename must match the name slug for auto-generated README version cell)
- Regenerate skills.sh.json and metadata.json: removes cufolio entry
  (was blocking the CI check gate since committed file diffed from generated output)

Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
2026-07-31 15:14:04 -05:00
Moshe Abramovitch 3e166b9e29 Regenerate marketplace metadata for omniverse-usd-performance-tuning
Picks up the SKILL.md description reworded in the 7/28 resync. Generated
with `generate-skill-metadata.py --no-ai`; 322 skills unchanged, 1
materially changed.

Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 18:08:35 -07:00
mosheabr 2787f1c0be chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-27 10:27:04 -05:00
mosheabr 38b7216a3e chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-21 15:56:20 -05:00
mosheabr 6fafa30491 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-21 14:10:23 -05:00
mosheabr 6379b9ce54 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-20 10:38:02 -05:00
mosheabr 55f1849994 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-17 18:03:43 -05:00
Moshe Abramovitch a713401445 fix(metadata): survive empty/malformed enrichment responses
The enrichment client capped completions at max_tokens=512. Reasoning
models spend that budget on hidden reasoning tokens before emitting any
visible content, so a skill whose classification needed longer reasoning
came back with empty content (finish_reason=length) on every run and was
silently excluded from metadata.json / skills.sh.json under the
partial-success policy (seen deterministically on
nemo-relay-debug-runtime-integration since 2026-07-16).

- Raise max_tokens to 4096; the JSON output is tiny, the headroom is
  for reasoning.
- Move response parsing inside the retry loop so an empty or garbled
  body is retried with backoff instead of permanently dropping the
  skill from that run's output.
- Include finish_reason and a content excerpt in the terminal error so
  the next such failure is diagnosable from the workflow log alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-17 17:45:09 -05:00
mosheabr e4bd907fd2 chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-17 11:57:33 -05:00
Jason Dudash 23ac085a4c Add nvidia-skill-finder catalog-only router skill
Catalog-only discovery/router skill staged via direct PR (no components.d
upstream); registered in catalog-exceptions.yml so the hourly sync won't
prune it. Includes the NVSkills validation signature (skill.oms.sig) and
the current benchmarks.json / metadata.json rollups.

History linearized into a single commit to replace the branch's merge
commits, which blocked the repo's rebase-merge (only allowed method) with
"Base branch was modified". Tree is identical to the prior branch tip.

Co-authored-by: nvskills-svc-account <svc-nvskills-signing@nvidia.com>
Signed-off-by: Jason Dudash <jdudash@nvidia.com>
2026-07-14 13:49:37 -04:00
Moshe Abramovitch f6075a5060 Read manual-components.yml as a component source; shrink exceptions to contributor skills
Per review: manual-components.yml already declares the five manually
staged Physical AI skills with their component name (and feeds README
regeneration). Listing them again in catalog-exceptions.yml created a
second source of truth. Now:

- The benchmarks aggregator and orphan pruner read manual-components.yml
  directly (catalog_dirs are expected, component name attributed), so
  the Physical AI team keeps one edit surface.
- catalog-exceptions.yml carries only truly uncataloged dirs
  (cuopt-developer), with its header documenting the three-tier
  registry: components.d, manual-components, exceptions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-09 14:31:31 -05:00
Moshe Abramovitch b70268e06c Attribute components for intentionally-unregistered skills via catalog-exceptions.yml
Six skills exist in the catalog without a components.d registration by
design (contributor-facing cuopt-developer; five manually curated
Physical AI Hub skills). Their component field in benchmarks.json was
null, rendering as 'Unmapped' on the adoption dashboard's component
view.

Let catalog-exceptions.yml entries declare a display component and use
it as a fallback in the benchmarks aggregator (components.d remains
authoritative where a registration exists). All 229 skills in the feed
now carry a component; output verified byte-stable.

Reported by Michael Raheem (dashboard component view), 2026-07-09.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-09 14:31:31 -05:00
mosheabr 153b14bfcb chore(metadata): regenerate metadata.json, skills.sh.json, and benchmarks.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-08 13:54:13 -05:00
Moshe Abramovitch 34b945b2dc Move catalog-exceptions.yml out of components.d/
The sync workflow, README regenerator, and metadata generator all glob
components.d/*.yml as the component registry. catalog-exceptions.yml
(added in #331) has no name/repo, so the sync manufactured a 'null'
component and reported 'null (null): clone failed' on every run —
first observed in sync PR #327.

Move the exceptions file to the repository root where no component
glob can sweep it, update the prune script path (and drop its now
unneeded skip-case), and update the docs. Verified locally: the
aggregated config has 33 components and zero null entries, and the
pruner still resolves exceptions correctly from the new path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-08 13:49:16 -05:00
Moshe Abramovitch 030b121cc4 Add orphan pruning to the skills sync
Deregistering a skill from components.d did not remove its catalog copy
— the sync only writes declared paths and never prunes. Three teams
(Dynamo, TAO, cuOpt) independently assumed deregistration removes the
dir, leaving stale skills live on the catalog and downstream surfaces.

- .github/scripts/prune-orphans.sh: after the sync loop, delete any
  top-level skills/ dir with no components.d registration and no entry
  in the exceptions file. Safety rails: pruning is skipped for the run
  if any component yml fails to parse (a parse error would make that
  component's skills look unregistered), and if more than PRUNE_CAP=5
  dirs would prune at once nothing is deleted — the list is surfaced
  for human triage instead.
- components.d/catalog-exceptions.yml: explicit allowlist for dirs that
  intentionally exist without a registration, seeded with the
  contributor-facing cuopt-developer and the five manually curated
  Physical AI Hub skills (which testing confirmed would otherwise be
  treated as orphans).
- sync-skills.yml: run the prune after compliance enforcement; register
  pruning as a change so a prune-only sync still opens a PR; list
  pruned dirs (and any over-cap skip) in the sync PR body.
- components.d/README.md: document that deregistration now removes the
  catalog copy on the next sync.

Tested locally against the live repo state: correctly identified all 11
current orphans, refused at the default cap, pruned exactly the 6
deregistered dirs with cap raised (exceptions honored), idempotent
after prune, and safe on parse errors, empty declared sets, and a
missing exceptions file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-08 09:10:58 -07:00
Moshe Abramovitch bc23b75d0f Flatten results to BI-friendly rows; key agent columns off table header
Review feedback from mraheem-arch:

- Replace nested per-skill results with a flat results[] array (one row
  per skill x dimension x agent, denormalized with catalog_dir and
  component) so BI tools can load it as a table and join on catalog_dir.
  skills[] remains as a flat per-skill summary with a has_results flag.
- Parse agent columns from the Results table header instead of assuming
  they match Agents Used order, so reordered or partial columns attach
  scores to the right agent.
- Bump schema_version to 2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-08 09:10:37 -07:00
Moshe Abramovitch b6602dfe61 Add --check drift gate and wire benchmarks.json into metadata workflow
- aggregate_benchmarks.py: add --check mode (exit 1 when benchmarks.json
  does not match skills/*/BENCHMARK.md); drop the embedded commit SHA so
  the checked-in file is byte-stable and drift-checkable.
- generate-skill-metadata.yml: validate benchmarks.json in PR mode,
  regenerate it in the post-sync/dispatch job, and include it in the
  change detection and the automated regeneration PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-08 09:10:37 -07:00
Moshe Abramovitch c41981308e Add aggregated benchmark data JSON (test)
Aggregate every skill's BENCHMARK.md evaluation report into a single
machine-readable benchmarks.json at the repo root, so downstream tooling
can consume per-skill scores and uplift-vs-baseline data without parsing
markdown.

- .github/scripts/aggregate_benchmarks.py walks skills/*/BENCHMARK.md,
  extracts the evaluation summary, agents, and per-dimension results
  (score + uplift per agent), maps each skill to its component via
  components.d/, and computes a per-skill average uplift.
- benchmarks.json covers all 235 skills; 212 have Tier-3 dimension
  results, 23 are listed under skills_without_results.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-08 09:10:37 -07:00
Moshe Abramovitch 61bf1c114f Fix product.primary mislabeling and remove tao-run-on-lepton orphan
Two generator bugs compounded to mislabel 9 TAO skills on downstream
surfaces that group by product.primary (e.g. build.nvidia.com):

- The components.d lookup map was keyed by the source-repo path from
  each yml entry, but build_skill_entry looks up the catalog path.
  Products whose source layout nests skills under subdirs (TAO:
  skills/models/<name>/) never matched, so all their skills fell
  through to AI enrichment, which guessed the product label from
  content ('Cosmos', 'Brev', 'TAO', 'TAO Toolkit API', 'DGX Cloud').
  Key the map by skills/<catalog_dir> instead.
- The component-derived product was only applied when the field was
  missing, so wrong carried values persisted forever. The registered
  component name (when it is a valid taxonomy value) is now
  authoritative over the carried baseline.

Also remove skills/tao-run-on-lepton/: deleted from the source repo
and from components.d/tao-toolkit.yml, but the sync never prunes
catalog dirs whose registration was removed, leaving a stale entry
live on downstream surfaces.

Regenerated metadata.json (234 skills; 8 product.primary corrections,
all TAO) and skills.sh.json with --no-ai; outputs verified byte-stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-08 09:10:14 -07:00
Moshe Abramovitch edd5b9b9ad Remove orphaned cuOpt skill dirs; update install docs and add update guidance
Post-consolidation cleanup, confirmed with the cuOpt team:

- Remove four skills/ dirs that were deregistered from components.d by
  the cuOpt consolidation but never deleted (the sync copies declared
  paths and does not prune): cuopt-numerical-optimization-api-python,
  cuopt-routing-formulation, cuopt-server-common, cuopt-skill-evolution.
  (cuopt-developer stays — intentionally uncataloged, contributor-facing.)
- README.md + docs/advanced-install.mdx: the install examples used the
  now-removed -api-python skill as the canonical name; swap all
  occurrences to the consolidated cuopt-numerical-optimization-api.
- README.md: add a "Keep Skills Up to Date" section covering
  npx skills update / list / check (all verified against the current
  CLI), so users refreshing installs pick up renames/consolidations.
- Regenerate metadata.json (231 skills) and skills.sh.json; outputs
  verified byte-stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Moshe Abramovitch <moshea@nvidia.com>
2026-07-07 16:53:21 -05:00
mosheabr 6b0704d675 chore(metadata): regenerate metadata.json and skills.sh.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-07 08:20:19 -05:00
mosheabr 91aabb4459 chore(metadata): regenerate metadata.json and skills.sh.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-06 08:25:35 -05:00
mosheabr a04cdc08a9 chore(metadata): regenerate metadata.json and skills.sh.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-07-01 17:22:42 -05:00
Jason Dudash 044e888715 feat(plugins): generate Cursor plugin alongside Claude and Codex
Add a Cursor track to the plugin build pipeline so each catalog plugin in
plugins.d/ also emits a .cursor-plugin/plugin.json manifest and is
registered in a top-level .cursor-plugin/marketplace.json, mirroring the
existing Claude (.claude-plugin/) and Codex (.codex-plugin/) tracks.

- build-plugins.py: add render_cursor_plugin_json() and
  upsert_cursor_marketplace(); wire both into build_catalog_plugin() and
  main(); include the cursor marketplace in the drift check.
- Cursor manifest omits the skills field so Cursor folder discovery scans
  skills/ (verified loading via cursor-agent --plugin-dir); projects the
  author down to {name}; strips the leading ./ from logo for
  raw.githubusercontent resolution.
- Add .cursor-plugin/marketplace.json (owner per Cursor schema); document
  marketplace_enabled.cursor in _defaults.yml and nvidia-skills.yml.
- validate-plugins.yml: watch .cursor-plugin/marketplace.json and document
  the Cursor validation story.
- Update plugins.d/README.md and the build-plugins.py docstring.

Signed-off-by: Jason Dudash <jdudash@nvidia.com>
2026-06-30 14:58:42 -05:00
mosheabr df4a9af45a chore(metadata): regenerate metadata.json and skills.sh.json
Generated by .github/workflows/generate-skill-metadata.yml.
2026-06-30 11:02:16 -05:00
mosheabr 2027d0a6a9 fix: use dual SPDX identifier per OSS page (CC-BY-4.0 AND Apache-2.0)
Correct the file headers and LICENSE preamble to match the OSS CC-BY-4.0/Apache-2.0
dual-license template (nvidia.atlassian.net OSS page 3151960247):
- File headers now use 'SPDX-License-Identifier: CC-BY-4.0 AND Apache-2.0' (was Apache-2.0)
  with SPDX-FileCopyrightText form, across the 7 catalog-owned files.
- LICENSE opens with the prescribed two-line dual-license preamble.

Signed-off-by: mosheabr <257371078+mosheabr@users.noreply.github.com>
2026-06-29 10:44:50 -05:00
mosheabr 85531b92b6 chore(license): OSS compliance — full CC-BY-4.0 text, DCO text, SPDX headers
Addresses OSS review (Bernd Weber):
- LICENSE: replace CC-BY-4.0 deed with full legal text (all 8 sections); fix copyright entity to NVIDIA CORPORATION & AFFILIATES.
- CONTRIBUTING.md: reproduce full DCO v1.1 text (a-d) in Signing Your Work.
- Add SPDX-License-Identifier headers to 5 catalog-owned scripts (.github/scripts/).
- Fix entity (NVIDIA Corporation -> NVIDIA CORPORATION & AFFILIATES.) in verify_content_integrity.py and generate-skill-metadata.py.

Note: the remaining 14 flagged files live under skills/ (synced from product source repos) and must be fixed at source; routed to owning teams separately.
Signed-off-by: mosheabr <257371078+mosheabr@users.noreply.github.com>
2026-06-29 10:44:50 -05:00