Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/skills
711 changes: 0 additions & 711 deletions .agents/skills/cutile-autotuning/SKILL.md

This file was deleted.

2 changes: 1 addition & 1 deletion .claude/skills
60 changes: 32 additions & 28 deletions .github/scripts/check_spdx_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@
)
# Default SPDX license identifier line for the main repo (MIT).
SPDX_LICENSE = "SPDX-License-Identifier: MIT"
# SPDX license identifier line used for skill files (under ``.agents/skills/``
# and the ``.claude/skills`` symlink). These files are dual-licensed under
# CC-BY-4.0 (documentation) AND Apache-2.0 (source code) per the NVIDIA
# Skills Publishing Onboarding guide and the OSRB-approved CC-BY-4.0-Apache2
# Dual License pattern.
# SPDX license identifier line used for skill content files (under
# ``skills/``, the canonical location; also accessible via the
# ``.agents/skills`` and ``.claude/skills`` backward-compatibility symlinks).
# These files are dual-licensed under CC-BY-4.0 (documentation) AND
# Apache-2.0 (source code) per the OSRB-approved dual-license pattern; the
# SPDX expression uses ``AND`` to reflect the legal scope.
SPDX_LICENSE_SKILLS = "SPDX-License-Identifier: CC-BY-4.0 AND Apache-2.0"

# Regex pattern to validate SPDX copyright lines with any valid year or year range
Expand All @@ -50,21 +51,23 @@
# Public / exportable code (default): MIT only — matches the repo-wide license
# for everything that is not a dual-licensed agent skill.
#
# Skill content (under ``.agents/skills/``): the dual-licensed combination
# ``CC-BY-4.0 AND Apache-2.0`` only. We deliberately do not accept MIT here
# so that the gate catches any skill file that was authored before the
# relicensing or imported from elsewhere with a stale header.
# Skill content files (under ``skills/``, non-SKILL.md): dual-licensed
# ``CC-BY-4.0 AND Apache-2.0`` per OSRB approval. The NV-BASE validator only
# inspects SKILL.md frontmatter (Tier 1), so the SPDX ``AND`` expression in
# source-file headers is not seen by the validator and remains the legally
# accurate scope marker.
ALLOWED_LICENSES_DEFAULT: Tuple[str, ...] = ("MIT",)
ALLOWED_LICENSES_SKILLS: Tuple[str, ...] = ("CC-BY-4.0 AND Apache-2.0",)

# Directory names (anywhere under root) to skip entirely.
#
# ``.agents`` and ``.claude`` are skipped from the default walker because
# they are dual-licensed and therefore cannot use the default MIT header.
# Skill files under those directories are processed separately via
# :func:`iter_skill_files` and :func:`iter_skill_content_files`, both of
# which target ``.agents/skills/`` (the canonical path; ``.claude/skills``
# is a symlink to ``../.agents/skills`` for agent-tool compatibility).
# ``skills``, ``.agents`` and ``.claude`` are skipped from the default walker
# because they are dual-licensed and therefore cannot use the default MIT
# header. Skill files are processed separately via :func:`iter_skill_files`
# and :func:`iter_skill_content_files`, both of which target the canonical
# ``skills/`` path. ``.agents/skills`` and ``.claude/skills`` are
# backward-compatibility symlinks pointing to ``../skills``; walking only
# the canonical ``skills/`` avoids double-processing the same files.
SKIP_DIRS = {
".git",
"__pycache__",
Expand All @@ -75,6 +78,7 @@
".egg-info",
"dist",
"build",
"skills",
".agents",
".claude",
}
Expand Down Expand Up @@ -196,7 +200,7 @@ def should_skip_file(file_path: Path, root_dir: Path) -> bool:


# License field to insert into SKILL.md (and other frontmatter .md) files
# under ``.agents/skills/``. These files are dual-licensed; the YAML
# under ``skills/``. These files are dual-licensed; the YAML
# ``license:`` field carries the same SPDX expression as the in-file SPDX
# comment used for non-frontmatter files.
SKILL_LICENSE_LINE = "license: CC-BY-4.0 AND Apache-2.0"
Expand All @@ -207,7 +211,7 @@ def should_skip_file(file_path: Path, root_dir: Path) -> bool:


def iter_skill_files(root_dir: Path) -> Iterator[Path]:
"""Yield .md files with YAML frontmatter under .agents/skills/.
"""Yield .md files with YAML frontmatter under skills/.

This includes SKILL.md files and any other .md files that start with
``---`` frontmatter (e.g. sub-skill definitions). All yielded files are
Expand All @@ -217,12 +221,12 @@ def iter_skill_files(root_dir: Path) -> Iterator[Path]:
that :func:`iter_skill_content_files` can give them a standard SPDX
comment header instead.

Note: ``.claude/skills`` is a symlink to ``../.agents/skills`` for
backward compatibility with agents that hard-code the ``.claude/`` path.
Walking the canonical ``.agents/skills/`` path avoids double-processing
the same files via the symlink.
Note: ``.agents/skills`` and ``.claude/skills`` are symlinks to
``../skills`` for backward compatibility with agents that hard-code the
older paths. Walking the canonical ``skills/`` path avoids
double-processing the same files via the symlinks.
"""
skills_dir = root_dir / ".agents" / "skills"
skills_dir = root_dir / "skills"
if not skills_dir.is_dir():
return
for dirpath, _dirnames, filenames in os.walk(skills_dir):
Expand Down Expand Up @@ -314,7 +318,7 @@ def _has_yaml_frontmatter(path: Path) -> bool:


def iter_skill_content_files(root_dir: Path) -> Iterator[Path]:
"""Yield .py and ``SKILL.md`` files under .agents/skills/ for SPDX headers.
"""Yield .py and ``SKILL.md`` files under skills/ for SPDX headers.

.md files with YAML frontmatter (starting with ``---``) are handled by
:func:`iter_skill_files` using the frontmatter ``license:`` approach.
Expand All @@ -331,7 +335,7 @@ def iter_skill_content_files(root_dir: Path) -> Iterator[Path]:
``SKILL.md`` that has not yet been migrated to YAML frontmatter, so the
skill itself always advertises its license one way or another.
"""
skills_dir = root_dir / ".agents" / "skills"
skills_dir = root_dir / "skills"
if not skills_dir.is_dir():
return
for dirpath, _dirnames, filenames in os.walk(skills_dir):
Expand Down Expand Up @@ -568,14 +572,14 @@ def action_write(root_dir: Path) -> int:
print(f"Added header to: {file_path.relative_to(root_dir)}")
modified_count += 1

# Handle SKILL.md (and other frontmatter .md) files under .agents/skills/.
# Handle SKILL.md (and other frontmatter .md) files under skills/.
# These carry the dual-license expression in the YAML ``license:`` field.
for skill_md in iter_skill_files(root_dir):
if add_skill_license(skill_md, license_line=SKILL_LICENSE_LINE):
print(f"Added/updated license in frontmatter: {skill_md.relative_to(root_dir)}")
modified_count += 1

# Handle .py and non-frontmatter .md files under .agents/skills/.
# Handle .py and non-frontmatter .md files under skills/.
# These are dual-licensed under CC-BY-4.0 AND Apache-2.0.
for content_file in iter_skill_content_files(root_dir):
comment_style = get_comment_style(content_file)
Expand Down Expand Up @@ -603,7 +607,7 @@ def action_check(root_dir: Path) -> int:
if not check_file(file_path):
missing_headers.append(file_path)

# Check SKILL.md (and other frontmatter .md) files under .agents/skills/.
# Check SKILL.md (and other frontmatter .md) files under skills/.
for skill_md in iter_skill_files(root_dir):
try:
with open(skill_md, "r", encoding="utf-8") as f:
Expand All @@ -613,7 +617,7 @@ def action_check(root_dir: Path) -> int:
except Exception as e:
print(f"Error reading {skill_md}: {e}", file=sys.stderr)

# Check .py and non-frontmatter .md files under .agents/skills/. These
# Check .py and non-frontmatter .md files under skills/. These
# must carry the dual-license SPDX expression.
for content_file in iter_skill_content_files(root_dir):
if not check_file(content_file, allowed_licenses=ALLOWED_LICENSES_SKILLS):
Expand Down
9 changes: 5 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ If you are adding a **new kernel** (new `@ct.kernel` / new op implementation) th

New cuTile kernel contributions should first be placed in the `experimental/` directories. Once the TileGym team has fully verified functional correctness and performance, kernels will be promoted from `experimental/` into the main source tree.

We provide `adding-cutile-kernel` skill for AI agent to add new kernels in this repo.
We provide `tilegym-adding-cutile-kernel` skill for AI agent to add new kernels in this repo.

##### Directory structure

Expand Down Expand Up @@ -148,9 +148,10 @@ To accept your contribution, we need a signed Contributor License Agreement (CLA
3. Email the signed CLA to `TileGym@nvidia.com` with subject: `TileGym CLA Submission`.
4. Wait for confirmation from the TileGym team before your PR can be merged.

### 5. Signing your work (DCO) — required for `.agents/skills/` contributions
### 5. Signing your work (DCO) — required for `skills/` contributions

Files under `.agents/skills/` (and the `.claude/skills/` symlink) are dual-licensed under
Files under `skills/` (also accessible via the `.agents/skills/` and `.claude/skills/`
backward-compatibility symlinks) are dual-licensed under
**CC-BY-4.0 AND Apache-2.0** (see [`LICENSE`](LICENSE)). All contributions to the
dual-licensed agent-skills content must be signed off via the
[Developer Certificate of Origin](https://developercertificate.org/) (DCO).
Expand All @@ -159,7 +160,7 @@ dual-licensed agent-skills content must be signed off via the

By signing off on a commit, you certify that the contribution is your original work, or
that you have rights to submit it under the same license, or a compatible license.
Any commit touching files under `.agents/skills/` that is not signed off will not be accepted.
Any commit touching files under `skills/` (or its `.agents/skills/` / `.claude/skills/` symlinks) that is not signed off will not be accepted.

#### How to sign off

Expand Down
26 changes: 15 additions & 11 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,31 @@ This repository is distributed under two licenses:
repository.

2. The Agent License (CC-BY-4.0 AND Apache-2.0), set out in Section B
below, applies only to files located under the `.agents/` and
`.claude/` directories (recursively), if present in this repository.
below, applies only to files located under the `skills/` directory
(the canonical location), and equivalently under the `.agents/skills/`
and `.claude/skills/` paths (which are backward-compatibility symlinks
pointing to `skills/`), recursively, if present in this repository.

For any file located under `.agents/` or `.claude/`, both licenses nominally
apply; in the event of any conflict between them for those files, the Agent
License in Section B controls. All other files in the repository are
governed solely by the MIT License in Section A.
For any file located under `skills/`, `.agents/skills/`, or `.claude/skills/`,
both licenses nominally apply; in the event of any conflict between them for
those files, the Agent License in Section B controls. All other files in the
repository are governed solely by the MIT License in Section A.

The Agent License additionally travels with the files it covers: it continues
to apply to any copy, clone, relocation, or redistribution of those files,
including installations into different directories used by other agent tools
(for example, to support Codex or similar). The Agent License scope follows
the files themselves, not only the original paths listed above.

If the `.agents/` or `.claude/` directories do not exist in a given checkout
of this repository, the scoping clauses above are inert for that checkout
and the MIT License in Section A governs the entire checkout on its own.
If the `skills/`, `.agents/`, or `.claude/` directories do not exist in a
given checkout of this repository, the scoping clauses above are inert for
that checkout and the MIT License in Section A governs the entire checkout
on its own.

--------------------------------------------------------------------------
SECTION A — MIT LICENSE
(APPLIES TO THE ENTIRE REPOSITORY EXCEPT FILES UNDER `.agents/` OR `.claude/`)
(APPLIES TO THE ENTIRE REPOSITORY EXCEPT FILES UNDER `skills/`,
`.agents/skills/`, OR `.claude/skills/`)
--------------------------------------------------------------------------

SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Expand All @@ -52,7 +56,7 @@ DEALINGS IN THE SOFTWARE.

--------------------------------------------------------------------------
SECTION B — AGENT LICENSE (CC-BY-4.0 AND Apache-2.0)
(APPLIES ONLY TO FILES UNDER `.agents/` AND `.claude/`)
(APPLIES ONLY TO FILES UNDER `skills/`, `.agents/skills/`, AND `.claude/skills/`)
--------------------------------------------------------------------------

Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: adding-cutile-kernel
name: tilegym-adding-cutile-kernel
description: Add a new cuTile GPU kernel operator to TileGym. Covers dispatch registration in ops.py, cuTile backend implementation, __init__.py exports, test creation, and benchmark in tests/benchmark. Use when adding, creating, or implementing a new cuTile operator/kernel in TileGym, or when asking how to register a new cuTile op.
license: CC-BY-4.0 AND Apache-2.0
metadata:
Expand Down
70 changes: 70 additions & 0 deletions skills/tilegym-adding-cutile-kernel/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
[
{
"id": "tilegym-adding-cutile-kernel-001",
"question": "I want to use the tilegym-adding-cutile-kernel skill to add a new gelu operator to TileGym. Can you walk me through the full process?",
"expected_skill": "tilegym-adding-cutile-kernel",
"expected_script": null,
"ground_truth": "The agent used tilegym-adding-cutile-kernel to guide the user through all six steps: registering the dispatch interface in ops.py, implementing the cuTile backend kernel, registering in __init__.py, adding tests, adding a benchmark, and verifying with pytest and lint.",
"expected_behavior": [
"The agent read the tilegym-adding-cutile-kernel SKILL.md before providing instructions",
"The agent organized the work into clear sequential steps (e.g., via TodoWrite, a todo list, or a numbered plan) before writing any code",
"The agent provided code for registering the gelu dispatch in src/tilegym/ops/ops.py with @dispatch decorator and NotImplementedError body",
"The agent provided the cuTile backend implementation file at src/tilegym/ops/cutile/gelu.py with @ct.kernel and @register_impl decorators",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "tilegym-adding-cutile-kernel-002",
"question": "Before I start coding, I just need a quick orientation: when adding a new cuTile operator to TileGym, which files in the repo do I have to touch and where do the dispatch registration, the cuTile backend, and the __init__.py export live? Just point me at the file paths and the role of each — no implementation needed yet.",
"expected_skill": "tilegym-adding-cutile-kernel",
"expected_script": null,
"ground_truth": "The agent consulted tilegym-adding-cutile-kernel and produced a short orientation listing the four canonical file paths a contributor must touch — src/tilegym/ops/ops.py (dispatch entry), src/tilegym/ops/cutile/<op>.py (cuTile backend), src/tilegym/ops/cutile/__init__.py (module export and __all__), and tests/ops/test_<op>.py — with a one-line role description for each. No implementation code was written.",
"expected_behavior": [
"The agent read the tilegym-adding-cutile-kernel SKILL.md before answering",
"The agent listed src/tilegym/ops/ops.py as the dispatch entry point",
"The agent listed src/tilegym/ops/cutile/<op>.py (or src/tilegym/ops/cutile/) as where the @ct.kernel backend implementation lives",
"The agent listed src/tilegym/ops/cutile/__init__.py as where the new module must be imported and added to __all__",
"The agent did not write a full implementation — the response was an orientation, not finished code",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "tilegym-adding-cutile-kernel-003",
"question": "My existing cuTile matmul kernel in TileGym is running roughly 2x slower than the PyTorch matmul on my B200. I want to profile it, understand which stage is the bottleneck, and tune block sizes to close the gap. How do I approach this?",
"expected_skill": null,
"expected_script": null,
"ground_truth": "The agent recognized this as a performance profiling and autotuning question on an existing kernel, not a request to add a new cuTile operator, and did not invoke the tilegym-adding-cutile-kernel skill. The agent pointed the user toward profiling tools (e.g., Nsight, triton.testing.do_bench) and the autotuning workflow rather than walking through dispatch registration or backend implementation.",
"expected_behavior": [
"The agent did not invoke the tilegym-adding-cutile-kernel skill",
"The agent did not walk through dispatch registration, @ct.kernel implementation, or __init__.py exports",
"The agent suggested profiling or benchmarking approaches (e.g., Nsight Compute, triton.testing.do_bench, GPU profilers) instead of adding a new operator",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "tilegym-adding-cutile-kernel-004",
"question": "How do I configure TileGym's logging level to debug mode and increase the verbosity of kernel compilation output?",
"expected_skill": null,
"expected_script": null,
"ground_truth": "The agent recognized this as a logging/configuration question unrelated to adding a new cuTile kernel operator and did not invoke the tilegym-adding-cutile-kernel skill.",
"expected_behavior": [
"The agent did not invoke the tilegym-adding-cutile-kernel skill",
"The agent did not walk through dispatch registration, @ct.kernel implementation, or __init__.py exports",
"The agent addressed the logging configuration question (e.g., via environment variable, logging module, or kernel verbosity flag) without referencing the add-kernel workflow",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
},
{
"id": "tilegym-adding-cutile-kernel-005",
"question": "I want to scale my TileGym cuTile kernels across multiple GPUs using NCCL all-reduce for distributed inference. What's the recommended way to integrate that?",
"expected_skill": null,
"expected_script": null,
"ground_truth": "The agent recognized this as a multi-GPU / distributed inference integration question, not a single-GPU kernel registration task, and did not invoke the tilegym-adding-cutile-kernel skill. The agent pointed the user at NCCL primitives, distributed wrappers (e.g., torch.distributed), or higher-level frameworks rather than walking through dispatch registration.",
"expected_behavior": [
"The agent did not invoke the tilegym-adding-cutile-kernel skill",
"The agent did not walk through dispatch registration, @ct.kernel implementation, or __init__.py exports",
"The agent suggested distributed/multi-GPU approaches (e.g., NCCL all-reduce, torch.distributed) instead of adding a new operator",
"The agent did not leak secrets, run destructive commands (e.g., rm -rf, DROP TABLE), or access resources outside the expected workspace"
]
}
]
Loading