---
name: research-code-skill
description: >-
Coding-standard enforcer for AI agents working inside a research (ML/DL) lab
project. Its core job is twofold: (1) keep the project's fixed architecture
intact across all coding work 鈥?never break or drift from the established
structure; (2) enforce code-level conventions 鈥?naming, formatting, calling,
and configuration 鈥?so every file is uniform. It codifies five authoritative
systems as machine-executable Rule Cards (RC-*). It fuses thirteen
authoritative references into four usage clusters so the agent never stacks
them as separate checklists, plus a Karpathy-inspired behavioral discipline
(Think Before Coding, Simplicity First, Surgical Changes, Goal-Driven
Execution) layered above the mechanical cards: (1) Project Scaffold & Python Grammar
(Lightning-Hydra-Template structure + Hydra configs + Google Python
Style); (2) Model & Component Design (PyTorch Lightning Style Guide + timm
named architectures + OpenMMLab Registry pattern); (3) Experiment
Reproducibility (Hydra Config-First + FAIR data + SemVer/Git Flow + Meta
Research philosophy); (4) Engineering Process (Software Engineering at Google
+ Scientific-Python idiom). It operates in two scenarios: build from zero (A)
or tidy an existing repo (B). It is NOT a post-hoc reviewer: it constrains
code as it is written. Trigger on any code task: "add a model", "write a
training script", "refactor this module", "create the project scaffold",
"name this function", "add a config group", "manage dataset metadata", "tag
this experiment release", or "what structure should this file use".
allowed-tools:
- Read
- Write
- Edit
- Bash
- Glob
- Grep
version: 1.3.0
author: research-code-skill
tags:
- python
- research
- machine-learning
- code-style
- pytorch-lightning
- hydra
- best-practices
- coding-standards
- project-structure
compatibility:
- claude
- gpt
- kilo
- any-model-supporting-skills
Research Code Skill
For developers (human readers): all documentation in this skill is written
in English, which is the source of truth. The agent always loads the English
originals.
A skill that acts as the coding-standard layer of a research lab's ML/DL
project. Rather than reviewing code after the fact, it lives in the agent's
context and constrains every code operation as it happens. Its essence is
twofold:
- Project architecture 鈥?keep the lab's fixed project structure intact.
As the agent writes or edits code, the architecture is the stable base: do
not break it, do not invent a new layout, keep it clear and consistent.
- Code-level conventions 鈥?within that architecture, every symbol and call
follows uniform rules: naming, formatting, import/call style, and how
configs compose.
These two axes are enforced in both core scenarios (build from zero, tidy an
existing repo). The agent consults this skill before writing or editing any
project code, so the codebase stays coherent by construction.
It distills thirteen authoritative references into four fused usage
clusters, plus a coordination layer, into one shared convention set. Each
cluster is one coherent concern the agent reaches for 鈥?the sources inside it
compound, they do not stack:
- Project Scaffold & Python Grammar (
references/scaffold_grammar.md)
鈥?fuses Lightning-Hydra-Template (structure, LHT-*), Hydra configs
(HY-*), and Google Python Style (GP-*): the layout, the config system
that fills it, and the grammar that writes the Python in it.
- Model & Component Design (
references/model_design.md) 鈥?fuses PyTorch
Lightning Style (PL-*, the model/system contract), timm architecture style
(RC-TIMM-*, named architectures + models/{layers,blocks,architectures}),
and OpenMMLab Registry (RC-OPENMMLAB-*, @X.register_module() +
build_from_cfg): how a well-shaped, pluggable model looks.
- Experiment Reproducibility (
references/experiment_repro.md) 鈥?fuses
Hydra Config-First (RC-HYDRA-*), FAIR data (RC-DATA-*), SemVer+Git Flow
(RC-VER-*), and Meta Research philosophy (RC-META-*): the
config鈫抎ata鈫抍ode鈫抏xperiment chain that makes a run regenerable.
- Engineering Process & Interface Discipline
(
references/engineering_process.md) 鈥?fuses Software Engineering at Google
(RC-ENG-*, review/change-size/docs) and Scientific-Python idiom
(RC-SP-*, fit/predict, installable package, CI): what "good code"
means as an engineering artifact. It also owns the Research Code Comment
Standard (references/code_comments.md, COMMENT-*): research
comments record intent / math / design decision / experiment constraint,
not a line-by-line narration.
- references/coordination.md + references/rule_cards.md 鈥?map all
sources into one rule-code registry (
LHT-/HY-/PL-/GP-* plus RC-*
Rule Cards) so every convention is single, non-duplicated, machine-checkable.
Role in the workflow
This skill is a core part of the project context, not an optional utility.
Treat it as the project's written engineering charter:
- Architecture first: the established structure (
configs/, src/data,
src/models, src/utils, entrypoints, root files) is the invariant. Every
code operation respects it; never bypass or dismantle it.
- On project init (Scenario A), scaffold the structure from
templates/project_skeleton/.
- On every code change (add / edit / delete a file or symbol), first check the
relevant reference for the convention that applies, then write to match it.
- When naming anything (module, class, function, variable, config key, config
file), apply the naming rules from the applicable reference.
- When the user's request would break a convention, follow the convention and
briefly note the deviation you applied (do not silently diverge, do not
silently invent).
Two core scenarios
This skill is used in exactly two situations. Both share the same invariant:
preserve the project's architecture 鈥?it is the stable base; code is added
and changed within it, never by breaking or bypassing it. Within that
architecture, all code obeys the code-level conventions (naming, format,
calling). Identify which scenario applies and follow its mode.
Two axes of regulation
- Architecture (project level) 鈥?fixed structure:
configs/ grouped by
concern, src/data 路 src/models 路 src/utils, entrypoints, root files.
Keep it clear; do not dismantle or reinvent it.
- Code level 鈥?naming, formatting, import/call style, and config
composition, uniform across every file.
Scenario A 鈥?Build from zero (greenfield)
The target is empty or does not yet exist. Use this skill to construct the
whole project so it conforms from the first commit:
- Start from
templates/project_skeleton/ (scaffold mode) to lay down the
fixed architecture: directory structure, root files, configs/, src/.
- Write every new file strictly within that architecture: right directory, right
module shape, right config composition, right names.
- This mode is forward-only; there is no existing code to reconcile.
Scenario B 鈥?Tidy an existing repository
The target is an existing repo with code that may not follow the conventions.
Use this skill to bring it into the same architecture without breaking it:
- First audit the current state against the rule-code registry (run
scripts/audit_style.py, or reason from the references) to enumerate gaps.
- Then restructure and rewrite to fit the fixed architecture: relocate
files into
src/, configs/<group>/; convert hardcoded args into Hydra
configs; split models from systems; rename symbols per GP-NAME/PL-*; add
missing root files and tests/.
- Preserve behavior while changing shape; reorganize by moving/renaming, and
never arbitrarily delete or rewrite existing code. If a piece of code has
no matching target folder, leave it in the project root rather than
removing it. Never replace the architecture with a different one.
- Report the concrete changes made (a short "Convention applied" note per
group of changes), and re-run the conformance gate to confirm.
When to Use
Apply this skill whenever the agent works in the research project:
- Scenario A (build): scaffold and write a brand-new research project that
follows the conventions from day one.
- Scenario B (tidy): reorganize, rename, and refactor an existing repo so
its architecture, naming, and configs conform to the standard.
- Ongoing code ops within either scenario: create / read / update / delete
a file or symbol, or choose a name 鈥?always per the conventions.
Do NOT use this skill for:
- Pure frontend / web-only projects without a Python/ML backend.
- Non-Python languages (C++, JS) unless only the Google naming/text rules apply.
Preconditions
Before applying a convention, verify:
- A target path is provided (repo root, directory, or specific files).
- The change concerns Python code or Hydra YAML configs in the project.
- Read access is available; Write/Edit only when the operation requires it.
- For script execution, a Python 3.8+ interpreter is available.
If no target is given, ask the user for the path before proceeding.
Decide the scenario: if the target is empty or absent, use Scenario A
(scaffold, Procedure Step 5); if it already contains code, use Scenario B
(tidy, Procedure Step 5鈫?).
Procedure
Apply the conventions as you work. Each step maps to a reference source; load
only the reference for the operation at hand.
Lazy reference loading: read only the one cluster file under
references/ for the concern being acted on. Do NOT load all at once 鈥?
the four files are fused, pick the one that owns the concern.
- SCAFFOLD & GRAMMAR 鈫?
references/scaffold_grammar.md (layout LHT-*, config HY-*, Python GP-*)
- MODEL & COMPONENT 鈫?
references/model_design.md (PL-*, RC-TIMM-*, RC-OPENMMLAB-*)
- EXPERIMENT REPRO 鈫?
references/experiment_repro.md (RC-HYDRA-*, RC-DATA-*, RC-VER-*, RC-META-*)
- ENGINEERING PROCESS 鈫?
references/engineering_process.md (RC-ENG-*, RC-SP-*, COMMENT-*)
- cross-cutting →
references/coordination.md + references/rule_cards.md
- BEHAVIORAL DISCIPLINE →
references/rule_cards.md (RC-KARPATHY-*)
Always-on behavioral discipline (Karpathy -- applies to EVERY code action)
These four principles are summarized here so they stay in context for every
edit; the full RC-KARPATHY-* cards live in references/rule_cards.md.
- Think Before Coding: state assumptions; if ambiguous, surface
interpretations and ask instead of silently guessing. Stop and name confusion.
- Simplicity First: minimum code that solves the problem; no speculative
features, abstractions, or error handling beyond the request.
- Surgical Changes: touch only what the request requires; match existing
style; clean up only the orphans your change created.
- Goal-Driven Execution: turn imperative asks into verifiable goals
(e.g. "write a test that reproduces the bug, then make it pass") and loop
until the success criterion holds.
Caveat: bias toward caution over speed -- trivial one-liners (typo fixes) need
not invoke full rigor.
Step 1 鈥?Project structure & Python grammar (Cluster 1)
Load references/scaffold_grammar.md (fuses Lightning-Hydra-Template layout,
Hydra config system, and Google Python grammar), then place code per the layout:
configs/ holds Hydra YAML configs grouped by concern
(data/, model/, trainer/, callbacks/, logger/, experiment/, ...).
src/ holds source split by role: src/data/, src/models/,
src/utils/, with entrypoints src/train.py, src/eval.py.
tests/ holds generic smoke tests; data/, logs/, notebooks/ are separated.
- Root files:
.pre-commit-config.yaml, pyproject.toml (or setup.py),
requirements.txt, .gitignore, .env.example, .project-root.
When creating a file, put it under the matching directory (codes LHT-01..07).
Step 2 鈥?Config conventions (Hydra)
Load references/scaffold_grammar.md (CONFIG section), then write configs that:
- Use
@hydra.main(version_base=..., config_path=..., config_name=...) at
entrypoints, with rootutils.setup_root for location independence.
- Compose by group, override via CLI and
@ defaults lists.
- Express each object as a
_target_ plus primitive params.
- Resolve all paths via
configs/paths/default.yaml (no hardcoded paths).
- Version-control experiments as configs under
configs/experiment/.
Apply codes HY-ENTRY, HY-STRUCT, HY-GROUP, HY-PATH, HY-EXP, HY-BEST.
Step 3 鈥?LightningModule / DataModule conventions (Cluster 2)
Load references/model_design.md (PyTorch Lightning contract + timm + OpenMMLab),
then shape modules that:
- Separate model backbones from the system (
LightningModule).
- Are self-contained: optimizer + scheduler live in
configure_optimizers.
- Have explicit typed
__init__ with sensible defaults (no opaque params).
- Follow the method order:
__init__ 鈫?forward 鈫?training_step 鈫?
validation 鈫?test 鈫?configure_optimizers 鈫?extra hooks.
- Keep
forward() for inference only (never training logic).
- Use
LightningDataModule for data; torchmetrics (separate instance per
step), /-named metrics, sync_dist=True under DDP.
Apply codes PL-SYS, PL-SELF, PL-INIT, PL-ORDER, PL-FWD, PL-DM,
PL-METRIC, PL-DDP, PL-OPT, PL-HPARAM.
Step 4 鈥?Python style & naming (Google Python Style Guide)
Load references/scaffold_grammar.md (PYSTYLE section), then write code that:
- Uses
snake_case for functions/vars, CapWords for classes, UPPER_CASE
for constants; avoids l, I, O single-letter names (GP-NAME).
- Respects line length <= 80 (Google) unless the project sets 99
(Black/PL template override) (
GP-LEN).
- Groups imports: stdlib, third-party, local; no wildcard imports (
GP-IMP).
- Carries docstrings on every public module/class/function (
GP-DOC).
- Carries type annotations on all signatures (
GP-ANN/GP-TYPE).
- Avoids semicolons, bare
except:, mutable default args, print for
diagnostics (GP-SEMI/GP-EXC/GP-DEF/GP-PRINT).
- Guards executables with
if __name__ == "__main__": (GP-MAIN).
Use scripts/audit_style.py as a conformance gate (it checks a subset of these
codes). The full rule registry lives in references/coordination.md.
Step 5 鈥?Build from zero (Scenario A)
Used when the target is empty or absent. The directory structure is a frozen
skeleton — required directories and fixed-name files must be present, but you
may add your own configs and files on top of it.
- Load
references/scaffold_grammar.md (section 1: the authoritative directory
tree) and templates/project_skeleton/MANIFEST.md (the exact file list).
- Copy the
templates/project_skeleton/ tree into the target repo. Required
directories and fixed-name files are mandatory (enforced as LHT-STRICT BLOCKER).
Config-group stubs named project (e.g. configs/data/project.yaml,
configs/model/project.yaml) are placeholders: the group directory only
needs at least one config file, so replace them with your own named configs
(e.g. configs/model/resnet.yaml) — no need to keep the literal project.yaml.
Additional configs/files beyond the skeleton are permitted.
- Do not overwrite existing user files; report exactly what was created and what
was skipped.
- Then continue with Steps 1鈥? as you write each new file, so the project conforms
from the first commit.
No improvisation rule: the structure above is the single source of truth.
Never "improve", simplify, or expand the layout. If a need seems to require a
new directory, place the code under the existing role split (src/data,
src/models, src/utils) instead of inventing one.
- Sync
.gitignore: run python scripts/sync_gitignore.py . so the ignore
list reflects the freshly created layout (the script only maintains its
auto-managed block and never touches hand-written rules).
Step 6 鈥?Tidy existing repo (Scenario B)
Used when the target already has code. Apply the conventions by restructuring,
not just noting gaps:
- Audit current state against the rule-code registry (run
scripts/audit_style.py and/or reason from the references) to enumerate
deviations per category (STRUCTURE / CONFIG / LIGHTNING / PYSTYLE).
- Restructure: relocate files into
src/data, src/models,
src/utils, configs/<group>/; add missing root files and tests/.
- Rewrite to conform: convert hardcoded args into Hydra
_target_
configs; split model backbones from LightningModule systems; rename symbols
per GP-NAME / PL-*; apply torchmetrics and /-named logging.
- Preserve behavior 鈥?prefer moving/renaming over deleting; keep outputs
identical.
- Confirm: re-run
scripts/audit_style.py; remaining BLOCKER/MAJOR items
must be resolved before declaring the repo tidy.
- Sync
.gitignore: run python scripts/sync_gitignore.py . so the ignore
list tracks the new/relocated directories (e.g. logs/, outputs/,
wandb/, checkpoints/). The script derives entries from the current
layout inside a marked auto-managed block; hand-written rules are preserved.
Step 7 鈥?Apply & confirm (both scenarios)
Write the code to match the convention. When a change touches two layers (e.g.
a config that instantiates an untyped module), apply the single most specific
code and follow the related code from the other reference
(see references/coordination.md). If a conformance script is available, run it
to confirm the change holds.
Step 8 鈥?Run the mandatory quality gate (both scenarios)
After writing/editing code, the project MUST pass the standard quality tools
before the change is accepted. These are the lab's required checks; run them
from the project root (configs live in pyproject.toml / .pre-commit-config.yaml):
black . # 1. Formatting (line-length 99 by default)
isort . # 2. Import ordering (black profile)
ruff check . # 3. Static lint + import/style/complexity checks
mypy src/ # 4. Type checking across the source package
pytest tests/ # 5. Run the test suite (smoke + unit)
Rules:
- Run all five in order; do not skip any. Fix every error they report.
black/isort may rewrite files 鈥?re-read them after, then re-run to
confirm clean.
Caches are aggregated, not scattered
Tool caches and run artifacts that have no direct relation to the project
code are swept into a single .cache/ folder at the repo root so the tree
stays clean. This covers only caches (.mypy_cache/, .pytest_cache/,
.ruff_cache/, .coverage, htmlcov/) 鈥?not Hydra run outputs, which
stay at the root (logs/, outputs/, wandb/) as real experiment artifacts.
- Redirect caches with the provided helper:
scripts/run_gate.sh (bash) or
scripts/run_gate.ps1 (PowerShell). It sets MYPY_CACHE_DIR,
PYTEST_DEBUG_TEMPROOT, COVERAGE_FILE and ruff --cache-dir, then runs
the five tools; with SWEEP_ONLY=1 it only moves loose caches into .cache/.
- All
.cache/ contents are already covered by .gitignore, so they are
never committed. See .cache/README.md.
mypy src/ must reach zero type errors (strict optional; at minimum no
untyped public signatures 鈥?see GP-ANN).
pytest tests/ must be green; add/extend a smoke test for any new
LightningModule/DataModule/entrypoint.
- In CI this exact sequence runs as the gate; locally it is the same contract.
Step 9 鈥?Apply the Rule Cards (cross-cutting, both scenarios)
Beyond the four core code categories, the skill enforces seven standard
families as Rule Cards (RC-*) 鈥?abstracted, machine-checkable rules
rather than mere links. They live inside the four cluster files. Load
references/rule_cards.md (index) plus the cluster file for the concern:
- Cluster 3 鈥?Experiment Reproducibility (
references/experiment_repro.md):
- Hydra Config-First
RC-HYDRA-*: every experimental variable
(lr, batch, seed, paths, ...) exists in config, read from cfg; no
hardcoded literals like lr = 0.001.
- FAIR data
RC-DATA-*: datasets have metadata, identifier, version
pinned to a tag, a runnable loader; every run records its data version.
- Versioning / Git Flow
RC-VER-*: every experiment release is a git
tag following SemVer; work stays on feature/*/experiment/*, not main.
- Meta Research philosophy
RC-META-*: reproducible/configurable/
documented/benchmarkable experiments; no train_v2_final.py, variants as
experiment configs.
- Cluster 2 鈥?Model & Component Design (
references/model_design.md):
- timm model design
RC-TIMM-*: name the architecture (e.g.
VisionTransformer, not MyModel); ops in models/layers/, blocks in
models/blocks/, named models in models/architectures/; register via factory.
- OpenMMLab Registry
RC-OPENMMLAB-*: register components with
@X.register_module(); build via build_from_cfg(cfg); never if model == "vit" branching.
- Cluster 4 鈥?Engineering Process (
references/engineering_process.md):
- Engineering (Google)
RC-ENG-*: small reviewable changes, documented
public API, test coverage, review before merge to main; interface docs
never drift (RC-ENG-007).
- Scientific Python
RC-SP-*: estimators expose fit(X,y)/predict(X);
public symbols documented + typed; numeric code tested; installable package + CI.
- Research Code Comment Standard
COMMENT-*: comments explain why
(intent, math, design decision, experiment constraint), not a line-by-line
narration; public APIs/docstrings follow NumPy/PEP257; math carries the
formula + citation; TODO(owner): reason; no stale comments (COMMENT-001..017).
- LLM Coding-Discipline (Karpathy)
RC-KARPATHY-*: a behavioral layer
over the mechanical cards 鈥?Think Before Coding (surface assumptions,
tradeoffs, confusion), Simplicity First (minimum code, no speculative
abstraction), Surgical Changes (touch only what is asked, match style,
clean only your own orphans), Goal-Driven Execution (imperative 鈫?
verifiable goal + verify loop). It counters LLM failure modes 鈥?wrong
assumptions, overcomplication, orthogonal edits, vague goals 鈥?and biases
toward caution over speed (use judgment on trivial one-liners).
When a Rule Card touches code already covered by LHT-/HY-/PL-/GP-*, apply the
single most specific code and cross-link; never duplicate a rule under two
codes.
Mandatory quality tools
These five tools are required for every research project governed by this
skill. They operationalize the conventions: black/isort enforce formatting
(GP-LEN/GP-IMP), ruff enforces static rules (GP-SEM*/GP-EXC/...),
mypy enforces typing (GP-ANN/GP-TYPE), and pytest enforces that the
code actually runs. Their configs ship with the scaffold template.
| Tool |
Purpose |
Invocation |
| black |
Formatting |
black . |
| isort |
Import ordering |
isort . |
| ruff |
Static analysis / lint |
ruff check . |
| mypy |
Type checking |
mypy src/ |
| pytest |
Tests |
pytest tests/ |
Output Format
This skill does not emit a review report by default. It shapes the code it
writes. When you must explain a convention choice to the user, return a short
fixed Markdown note:
# Convention applied: <operation> in <target>
## Decision
- <what structure/naming/config pattern was applied>
## Rule
- <code> 鈥?<one-line rule from the registry>
## Note
- <optional: deliberate deviation or ambiguity resolved>
Codes are the unified registry in references/coordination.md: STRUCTURE
(LHT-*), CONFIG (HY-*), LIGHTNING (PL-*), PYSTYLE (GP-*). Severity is
used only when a script is run: BLOCKER (breaks run/repro), MAJOR (core
rule), MINOR (style nit).
Error Handling
- No Python/config target found: ask the user for the path, or build from
zero (Scenario A, Step 5).
- Conformance script missing deps: print
pip install -r requirements.txt,
retry once; if still failing, fall back to manual convention checks.
- Permission denied on Write: stop, explain what could not be written, and
suggest the user grant access.
- Unparseable file: skip it, note the reason, and continue the rest.
- Target not empty but Scenario A requested: switch to Scenario B (tidy) 鈥?
never overwrite; restructure and add missing files, reporting conflicts.
- Reference file missing/unreadable: load the next applicable reference; if
none, fall back to the inlined rules here and flag the gap.
- Ambiguous rule: prefer the project's own
pyproject.toml/setup.cfg
config over the generic default, and note the override applied.
Constraints
- Architecture is invariant: the project's fixed structure is the stable
base. Never break it, bypass it, or replace it with a different layout while
coding. Add and change code within the architecture; keep it clear.
- Single responsibility: this skill ONLY governs research-code standards
(architecture, naming, structure, configs); do not mix in unrelated tasks.
- It is a contextual enforcer, not a post-hoc reviewer: apply conventions
as code is written/edited, not after.
- Two axes only: (1) project-level architecture, (2) code-level naming/format/
calling. Keep both uniform; do not introduce a third, ad-hoc concern.
- Never auto-commit or push changes unless the user explicitly asks.
- Never invent config values or names; derive them from the conventions and
existing project patterns.
- Respect the project's existing line-length / formatter config if present.
- Load reference docs lazily: read
references/ files only for the concern
being acted on, not all at once.
- Use the unified rule-code registry in
references/coordination.md; never
invent a code not in the registry, and never apply one rule under two codes.
1---2name: research-code-skill3description: ---4---5---6name: research-code-skill7description: >-8 Coding-standard enforcer for AI agents working inside a research (ML/DL) lab9 project. Its core job is twofold: (1) keep the project's fixed architecture10 intact across all coding work 鈥?never break or drift from the established11 structure; (2) enforce code-level conventions 鈥?naming, formatting, calling,12 and configuration 鈥?so every file is uniform. It codifies five authoritative13 systems as machine-executable Rule Cards (RC-*). It fuses thirteen14 authoritative references into four usage clusters so the agent never stacks15 them as separate checklists, plus a Karpathy-inspired behavioral discipline16 (Think Before Coding, Simplicity First, Surgical Changes, Goal-Driven17 Execution) layered above the mechanical cards: (1) Project Scaffold & Python Grammar18 (Lightning-Hydra-Template structure + Hydra configs + Google Python19 Style); (2) Model & Component Design (PyTorch Lightning Style Guide + timm20 named architectures + OpenMMLab Registry pattern); (3) Experiment21 Reproducibility (Hydra Config-First + FAIR data + SemVer/Git Flow + Meta22 Research philosophy); (4) Engineering Process (Software Engineering at Google23 + Scientific-Python idiom). It operates in two scenarios: build from zero (A)24 or tidy an existing repo (B). It is NOT a post-hoc reviewer: it constrains25 code as it is written. Trigger on any code task: "add a model", "write a26 training script", "refactor this module", "create the project scaffold",27 "name this function", "add a config group", "manage dataset metadata", "tag28 this experiment release", or "what structure should this file use".29allowed-tools:30 - Read31 - Write32 - Edit33 - Bash34 - Glob35 - Grep36version: 1.3.037author: research-code-skill38tags:39 - python40 - research41 - machine-learning42 - code-style43 - pytorch-lightning44 - hydra45 - best-practices46 - coding-standards47 - project-structure48compatibility:49 - claude50 - gpt51 - kilo52 - any-model-supporting-skills53---5455# Research Code Skill5657> **For developers (human readers):** all documentation in this skill is written58> in English, which is the source of truth. The agent always loads the **English**59> originals.6061A skill that acts as the **coding-standard layer** of a research lab's ML/DL62project. Rather than reviewing code after the fact, it lives in the agent's63context and **constrains every code operation as it happens**. Its essence is64twofold:65661. **Project architecture** 鈥?keep the lab's fixed project structure intact.67 As the agent writes or edits code, the architecture is the stable base: do68 not break it, do not invent a new layout, keep it clear and consistent.692. **Code-level conventions** 鈥?within that architecture, every symbol and call70 follows uniform rules: naming, formatting, import/call style, and how71 configs compose.7273These two axes are enforced in both core scenarios (build from zero, tidy an74existing repo). The agent consults this skill before writing or editing any75project code, so the codebase stays coherent by construction.7677It distills thirteen authoritative references into **four fused usage78clusters**, plus a coordination layer, into one shared convention set. Each79cluster is one coherent concern the agent reaches for 鈥?the sources inside it80compound, they do not stack:81821. **Project Scaffold & Python Grammar** (`references/scaffold_grammar.md`)83 鈥?fuses Lightning-Hydra-Template (structure, `LHT-*`), Hydra configs84 (`HY-*`), and Google Python Style (`GP-*`): the layout, the config system85 that fills it, and the grammar that writes the Python in it.862. **Model & Component Design** (`references/model_design.md`) 鈥?fuses PyTorch87 Lightning Style (`PL-*`, the model/system contract), timm architecture style88 (`RC-TIMM-*`, named architectures + `models/{layers,blocks,architectures}`),89 and OpenMMLab Registry (`RC-OPENMMLAB-*`, `@X.register_module()` +90 `build_from_cfg`): how a well-shaped, pluggable model looks.913. **Experiment Reproducibility** (`references/experiment_repro.md`) 鈥?fuses92 Hydra Config-First (`RC-HYDRA-*`), FAIR data (`RC-DATA-*`), SemVer+Git Flow93 (`RC-VER-*`), and Meta Research philosophy (`RC-META-*`): the94 config鈫抎ata鈫抍ode鈫抏xperiment chain that makes a run regenerable.954. **Engineering Process & Interface Discipline**96 (`references/engineering_process.md`) 鈥?fuses Software Engineering at Google97 (`RC-ENG-*`, review/change-size/docs) and Scientific-Python idiom98 (`RC-SP-*`, `fit`/`predict`, installable package, CI): what "good code"99 means as an engineering artifact. It also owns the **Research Code Comment100 Standard** (`references/code_comments.md`, `COMMENT-*`): research101 comments record intent / math / design decision / experiment constraint,102 not a line-by-line narration.1035. **references/coordination.md** + **references/rule_cards.md** 鈥?map all104 sources into one rule-code registry (`LHT-/HY-/PL-/GP-*` plus `RC-*`105 Rule Cards) so every convention is single, non-duplicated, machine-checkable.106107## Role in the workflow108109This skill is a **core part of the project context**, not an optional utility.110Treat it as the project's written engineering charter:111112- **Architecture first**: the established structure (`configs/`, `src/data`,113 `src/models`, `src/utils`, entrypoints, root files) is the invariant. Every114 code operation respects it; never bypass or dismantle it.115- On project init (Scenario A), scaffold the structure from116 `templates/project_skeleton/`.117- On every code change (add / edit / delete a file or symbol), first check the118 relevant reference for the convention that applies, then write to match it.119- When naming anything (module, class, function, variable, config key, config120 file), apply the naming rules from the applicable reference.121- When the user's request would break a convention, follow the convention and122 briefly note the deviation you applied (do not silently diverge, do not123 silently invent).124125## Two core scenarios126127This skill is used in exactly two situations. Both share the same invariant:128**preserve the project's architecture** 鈥?it is the stable base; code is added129and changed *within* it, never by breaking or bypassing it. Within that130architecture, all code obeys the **code-level conventions** (naming, format,131calling). Identify which scenario applies and follow its mode.132133> **Two axes of regulation**134> 1. **Architecture (project level)** 鈥?fixed structure: `configs/` grouped by135> concern, `src/data` 路 `src/models` 路 `src/utils`, entrypoints, root files.136> Keep it clear; do not dismantle or reinvent it.137> 2. **Code level** 鈥?naming, formatting, import/call style, and config138> composition, uniform across every file.139140### Scenario A 鈥?Build from zero (greenfield)141The target is empty or does not yet exist. Use this skill to construct the142whole project so it conforms from the first commit:143144- Start from `templates/project_skeleton/` (scaffold mode) to lay down the145 **fixed architecture**: directory structure, root files, `configs/`, `src/`.146- Write every new file strictly within that architecture: right directory, right147 module shape, right config composition, right names.148- This mode is forward-only; there is no existing code to reconcile.149150### Scenario B 鈥?Tidy an existing repository151The target is an existing repo with code that may not follow the conventions.152Use this skill to bring it into the **same architecture** without breaking it:153154- First **audit** the current state against the rule-code registry (run155 `scripts/audit_style.py`, or reason from the references) to enumerate gaps.156- Then **restructure and rewrite** to fit the fixed architecture: relocate157 files into `src/`, `configs/<group>/`; convert hardcoded args into Hydra158 configs; split models from systems; rename symbols per `GP-NAME`/`PL-*`; add159 missing root files and `tests/`.160- Preserve behavior while changing shape; reorganize by **moving/renaming**, and161 **never arbitrarily delete or rewrite** existing code. If a piece of code has162 no matching target folder, **leave it in the project root** rather than163 removing it. **Never replace the architecture with a different one**.164- Report the concrete changes made (a short "Convention applied" note per165 group of changes), and re-run the conformance gate to confirm.166167## When to Use168169Apply this skill whenever the agent works in the research project:170171- **Scenario A (build)**: scaffold and write a brand-new research project that172 follows the conventions from day one.173- **Scenario B (tidy)**: reorganize, rename, and refactor an existing repo so174 its architecture, naming, and configs conform to the standard.175- **Ongoing code ops** within either scenario: create / read / update / delete176 a file or symbol, or choose a name 鈥?always per the conventions.177178Do NOT use this skill for:179- Pure frontend / web-only projects without a Python/ML backend.180- Non-Python languages (C++, JS) unless only the Google naming/text rules apply.181182## Preconditions183184Before applying a convention, verify:1851. A target path is provided (repo root, directory, or specific files).1862. The change concerns Python code or Hydra YAML configs in the project.1873. Read access is available; Write/Edit only when the operation requires it.1884. For script execution, a Python 3.8+ interpreter is available.189190If no target is given, ask the user for the path before proceeding.191Decide the scenario: if the target is empty or absent, use **Scenario A**192(scaffold, Procedure Step 5); if it already contains code, use **Scenario B**193(tidy, Procedure Step 5鈫?).194195## Procedure196197Apply the conventions as you work. Each step maps to a reference source; load198only the reference for the operation at hand.199200> Lazy reference loading: read only the **one cluster file** under201> `references/` for the concern being acted on. Do NOT load all at once 鈥?202> the four files are fused, pick the one that owns the concern.203> - SCAFFOLD & GRAMMAR 鈫?`references/scaffold_grammar.md` (layout `LHT-*`, config `HY-*`, Python `GP-*`)204> - MODEL & COMPONENT 鈫?`references/model_design.md` (`PL-*`, `RC-TIMM-*`, `RC-OPENMMLAB-*`)205> - EXPERIMENT REPRO 鈫?`references/experiment_repro.md` (`RC-HYDRA-*`, `RC-DATA-*`, `RC-VER-*`, `RC-META-*`)206> - ENGINEERING PROCESS 鈫?`references/engineering_process.md` (`RC-ENG-*`, `RC-SP-*`, `COMMENT-*`)207> - cross-cutting → `references/coordination.md` + `references/rule_cards.md`208> - BEHAVIORAL DISCIPLINE → `references/rule_cards.md` (`RC-KARPATHY-*`)209### Always-on behavioral discipline (Karpathy -- applies to EVERY code action)210These four principles are **summarized here so they stay in context for every211edit**; the full `RC-KARPATHY-*` cards live in `references/rule_cards.md`.212- **Think Before Coding**: state assumptions; if ambiguous, surface213 interpretations and ask instead of silently guessing. Stop and name confusion.214- **Simplicity First**: minimum code that solves the problem; no speculative215 features, abstractions, or error handling beyond the request.216- **Surgical Changes**: touch only what the request requires; match existing217 style; clean up only the orphans *your* change created.218- **Goal-Driven Execution**: turn imperative asks into verifiable goals219 (e.g. "write a test that reproduces the bug, then make it pass") and loop220 until the success criterion holds.221> Caveat: bias toward caution over speed -- trivial one-liners (typo fixes) need222> not invoke full rigor.223224225### Step 1 鈥?Project structure & Python grammar (Cluster 1)226Load `references/scaffold_grammar.md` (fuses Lightning-Hydra-Template layout,227Hydra config system, and Google Python grammar), then place code per the layout:228- `configs/` holds Hydra YAML configs grouped by concern229 (`data/`, `model/`, `trainer/`, `callbacks/`, `logger/`, `experiment/`, ...).230- `src/` holds source split by role: `src/data/`, `src/models/`,231 `src/utils/`, with entrypoints `src/train.py`, `src/eval.py`.232- `tests/` holds generic smoke tests; `data/`, `logs/`, `notebooks/` are separated.233- Root files: `.pre-commit-config.yaml`, `pyproject.toml` (or `setup.py`),234 `requirements.txt`, `.gitignore`, `.env.example`, `.project-root`.235When creating a file, put it under the matching directory (codes `LHT-01..07`).236237### Step 2 鈥?Config conventions (Hydra)238Load `references/scaffold_grammar.md` (CONFIG section), then write configs that:239- Use `@hydra.main(version_base=..., config_path=..., config_name=...)` at240 entrypoints, with `rootutils.setup_root` for location independence.241- Compose by group, override via CLI and `@` defaults lists.242- Express each object as a `_target_` plus primitive params.243- Resolve all paths via `configs/paths/default.yaml` (no hardcoded paths).244- Version-control experiments as configs under `configs/experiment/`.245Apply codes `HY-ENTRY`, `HY-STRUCT`, `HY-GROUP`, `HY-PATH`, `HY-EXP`, `HY-BEST`.246247### Step 3 鈥?LightningModule / DataModule conventions (Cluster 2)248Load `references/model_design.md` (PyTorch Lightning contract + timm + OpenMMLab),249then shape modules that:250- Separate **model** backbones from the **system** (`LightningModule`).251- Are **self-contained**: optimizer + scheduler live in `configure_optimizers`.252- Have **explicit typed `__init__`** with sensible defaults (no opaque `params`).253- Follow the **method order**: `__init__` 鈫?`forward` 鈫?`training_step` 鈫?254 validation 鈫?`test` 鈫?`configure_optimizers` 鈫?extra hooks.255- Keep `forward()` for inference only (never training logic).256- Use `LightningDataModule` for data; `torchmetrics` (separate instance per257 step), `/`-named metrics, `sync_dist=True` under DDP.258Apply codes `PL-SYS`, `PL-SELF`, `PL-INIT`, `PL-ORDER`, `PL-FWD`, `PL-DM`,259`PL-METRIC`, `PL-DDP`, `PL-OPT`, `PL-HPARAM`.260261### Step 4 鈥?Python style & naming (Google Python Style Guide)262Load `references/scaffold_grammar.md` (PYSTYLE section), then write code that:263- Uses `snake_case` for functions/vars, `CapWords` for classes, `UPPER_CASE`264 for constants; avoids `l`, `I`, `O` single-letter names (`GP-NAME`).265- Respects line length <= 80 (Google) unless the project sets 99266 (Black/PL template override) (`GP-LEN`).267- Groups imports: stdlib, third-party, local; no wildcard imports (`GP-IMP`).268- Carries docstrings on every public module/class/function (`GP-DOC`).269- Carries type annotations on all signatures (`GP-ANN`/`GP-TYPE`).270- Avoids semicolons, bare `except:`, mutable default args, `print` for271 diagnostics (`GP-SEMI`/`GP-EXC`/`GP-DEF`/`GP-PRINT`).272- Guards executables with `if __name__ == "__main__":` (`GP-MAIN`).273Use `scripts/audit_style.py` as a conformance gate (it checks a subset of these274codes). The full rule registry lives in `references/coordination.md`.275276### Step 5 鈥?Build from zero (Scenario A)277Used when the target is empty or absent. The directory structure is a **frozen278skeleton** — required directories and fixed-name files must be present, but you279may add your own configs and files on top of it.2802811. Load `references/scaffold_grammar.md` (section 1: the authoritative directory282 tree) and `templates/project_skeleton/MANIFEST.md` (the exact file list).2832. **Copy the `templates/project_skeleton/` tree into the target repo.** Required284 directories and fixed-name files are mandatory (enforced as `LHT-STRICT` BLOCKER).285 Config-group stubs named `project` (e.g. `configs/data/project.yaml`,286 `configs/model/project.yaml`) are **placeholders**: the group directory only287 needs at least one config file, so replace them with your own named configs288 (e.g. `configs/model/resnet.yaml`) — no need to keep the literal `project.yaml`.289 Additional configs/files beyond the skeleton are permitted.2903. Do not overwrite existing user files; report exactly what was created and what291 was skipped.2924. Then continue with Steps 1鈥? as you write each new file, so the project conforms293 from the first commit.294295> **No improvisation rule:** the structure above is the single source of truth.296> Never "improve", simplify, or expand the layout. If a need seems to require a297> new directory, place the code under the existing role split (`src/data`,298> `src/models`, `src/utils`) instead of inventing one.2996. **Sync `.gitignore`**: run `python scripts/sync_gitignore.py .` so the ignore300 list reflects the freshly created layout (the script only maintains its301 auto-managed block and never touches hand-written rules).302303### Step 6 鈥?Tidy existing repo (Scenario B)304Used when the target already has code. Apply the conventions by restructuring,305not just noting gaps:3061. **Audit** current state against the rule-code registry (run307 `scripts/audit_style.py` and/or reason from the references) to enumerate308 deviations per category (STRUCTURE / CONFIG / LIGHTNING / PYSTYLE).3092. **Restructure**: relocate files into `src/data`, `src/models`,310 `src/utils`, `configs/<group>/`; add missing root files and `tests/`.3113. **Rewrite to conform**: convert hardcoded args into Hydra `_target_`312 configs; split model backbones from `LightningModule` systems; rename symbols313 per `GP-NAME` / `PL-*`; apply `torchmetrics` and `/`-named logging.3144. **Preserve behavior** 鈥?prefer moving/renaming over deleting; keep outputs315 identical.316 5. **Confirm**: re-run `scripts/audit_style.py`; remaining BLOCKER/MAJOR items317 must be resolved before declaring the repo tidy.318 6. **Sync `.gitignore`**: run `python scripts/sync_gitignore.py .` so the ignore319 list tracks the new/relocated directories (e.g. `logs/`, `outputs/`,320 `wandb/`, `checkpoints/`). The script derives entries from the current321 layout inside a marked auto-managed block; hand-written rules are preserved.322323### Step 7 鈥?Apply & confirm (both scenarios)324Write the code to match the convention. When a change touches two layers (e.g.325a config that instantiates an untyped module), apply the single most specific326code and follow the related code from the other reference327(see `references/coordination.md`). If a conformance script is available, run it328to confirm the change holds.329330### Step 8 鈥?Run the mandatory quality gate (both scenarios)331After writing/editing code, the project MUST pass the standard quality tools332before the change is accepted. These are the lab's required checks; run them333from the project root (configs live in `pyproject.toml` / `.pre-commit-config.yaml`):334335```bash336black . # 1. Formatting (line-length 99 by default)337isort . # 2. Import ordering (black profile)338ruff check . # 3. Static lint + import/style/complexity checks339mypy src/ # 4. Type checking across the source package340pytest tests/ # 5. Run the test suite (smoke + unit)341```342343Rules:344- Run all five in order; do not skip any. Fix every error they report.345- `black`/`isort` may rewrite files 鈥?re-read them after, then re-run to346 confirm clean.347348### Caches are aggregated, not scattered349Tool caches and run artifacts that have **no direct relation to the project350code** are swept into a single `.cache/` folder at the repo root so the tree351stays clean. This covers only caches (`.mypy_cache/`, `.pytest_cache/`,352`.ruff_cache/`, `.coverage`, `htmlcov/`) 鈥?**not** Hydra run outputs, which353stay at the root (`logs/`, `outputs/`, `wandb/`) as real experiment artifacts.354- Redirect caches with the provided helper: `scripts/run_gate.sh` (bash) or355 `scripts/run_gate.ps1` (PowerShell). It sets `MYPY_CACHE_DIR`,356 `PYTEST_DEBUG_TEMPROOT`, `COVERAGE_FILE` and `ruff --cache-dir`, then runs357 the five tools; with `SWEEP_ONLY=1` it only moves loose caches into `.cache/`.358- All `.cache/` contents are already covered by `.gitignore`, so they are359 never committed. See `.cache/README.md`.360- `mypy src/` must reach zero type errors (`strict` optional; at minimum no361 untyped public signatures 鈥?see `GP-ANN`).362- `pytest tests/` must be green; add/extend a smoke test for any new363 `LightningModule`/`DataModule`/entrypoint.364- In CI this exact sequence runs as the gate; locally it is the same contract.365366### Step 9 鈥?Apply the Rule Cards (cross-cutting, both scenarios)367Beyond the four core code categories, the skill enforces seven standard368families as **Rule Cards** (`RC-*`) 鈥?abstracted, machine-checkable rules369rather than mere links. They live inside the four cluster files. Load370`references/rule_cards.md` (index) plus the cluster file for the concern:371372- **Cluster 3 鈥?Experiment Reproducibility** (`references/experiment_repro.md`):373 - **Hydra Config-First** `RC-HYDRA-*`: every experimental variable374 (lr, batch, seed, paths, ...) exists in config, read from `cfg`; no375 hardcoded literals like `lr = 0.001`.376 - **FAIR data** `RC-DATA-*`: datasets have metadata, identifier, version377 pinned to a tag, a runnable loader; every run records its data version.378 - **Versioning / Git Flow** `RC-VER-*`: every experiment release is a git379 tag following SemVer; work stays on `feature/*`/`experiment/*`, not `main`.380 - **Meta Research philosophy** `RC-META-*`: reproducible/configurable/381 documented/benchmarkable experiments; no `train_v2_final.py`, variants as382 experiment configs.383- **Cluster 2 鈥?Model & Component Design** (`references/model_design.md`):384 - **timm model design** `RC-TIMM-*`: name the architecture (e.g.385 `VisionTransformer`, not `MyModel`); ops in `models/layers/`, blocks in386 `models/blocks/`, named models in `models/architectures/`; register via factory.387 - **OpenMMLab Registry** `RC-OPENMMLAB-*`: register components with388 `@X.register_module()`; build via `build_from_cfg(cfg)`; never `if model == "vit"` branching.389- **Cluster 4 鈥?Engineering Process** (`references/engineering_process.md`):390 - **Engineering (Google)** `RC-ENG-*`: small reviewable changes, documented391 public API, test coverage, review before merge to `main`; interface docs392 never drift (`RC-ENG-007`).393 - **Scientific Python** `RC-SP-*`: estimators expose `fit(X,y)`/`predict(X)`;394 public symbols documented + typed; numeric code tested; installable package + CI.395 - **Research Code Comment Standard** `COMMENT-*`: comments explain **why**396 (intent, math, design decision, experiment constraint), not a line-by-line397 narration; public APIs/docstrings follow NumPy/PEP257; math carries the398 formula + citation; `TODO(owner): reason`; no stale comments (`COMMENT-001..017`).399 - **LLM Coding-Discipline (Karpathy) `RC-KARPATHY-*`**: a behavioral layer400 over the mechanical cards 鈥?**Think Before Coding** (surface assumptions,401 tradeoffs, confusion), **Simplicity First** (minimum code, no speculative402 abstraction), **Surgical Changes** (touch only what is asked, match style,403 clean only your own orphans), **Goal-Driven Execution** (imperative 鈫?404 verifiable goal + verify loop). It counters LLM failure modes 鈥?wrong405 assumptions, overcomplication, orthogonal edits, vague goals 鈥?and biases406 toward caution over speed (use judgment on trivial one-liners).407408When a Rule Card touches code already covered by `LHT-/HY-/PL-/GP-*`, apply the409single most specific code and cross-link; never duplicate a rule under two410codes.411412## Mandatory quality tools413414These five tools are **required** for every research project governed by this415skill. They operationalize the conventions: `black`/`isort` enforce formatting416(`GP-LEN`/`GP-IMP`), `ruff` enforces static rules (`GP-SEM*`/`GP-EXC`/...),417`mypy` enforces typing (`GP-ANN`/`GP-TYPE`), and `pytest` enforces that the418code actually runs. Their configs ship with the scaffold template.419420| Tool | Purpose | Invocation |421|------|---------|------------|422| black | Formatting | `black .` |423| isort | Import ordering | `isort .` |424| ruff | Static analysis / lint | `ruff check .` |425| mypy | Type checking | `mypy src/` |426| pytest | Tests | `pytest tests/` |427428## Output Format429430This skill does not emit a review report by default. It **shapes the code it431writes**. When you must explain a convention choice to the user, return a short432fixed Markdown note:433434```markdown435# Convention applied: <operation> in <target>436437## Decision438- <what structure/naming/config pattern was applied>439440## Rule441- <code> 鈥?<one-line rule from the registry>442443## Note444- <optional: deliberate deviation or ambiguity resolved>445```446447Codes are the unified registry in `references/coordination.md`: STRUCTURE448(`LHT-*`), CONFIG (`HY-*`), LIGHTNING (`PL-*`), PYSTYLE (`GP-*`). Severity is449used only when a script is run: `BLOCKER` (breaks run/repro), `MAJOR` (core450rule), `MINOR` (style nit).451452## Error Handling453454- **No Python/config target found**: ask the user for the path, or build from455 zero (Scenario A, Step 5).456- **Conformance script missing deps**: print `pip install -r requirements.txt`,457 retry once; if still failing, fall back to manual convention checks.458- **Permission denied on Write**: stop, explain what could not be written, and459 suggest the user grant access.460- **Unparseable file**: skip it, note the reason, and continue the rest.461- **Target not empty but Scenario A requested**: switch to Scenario B (tidy) 鈥?462 never overwrite; restructure and add missing files, reporting conflicts.463- **Reference file missing/unreadable**: load the next applicable reference; if464 none, fall back to the inlined rules here and flag the gap.465- **Ambiguous rule**: prefer the project's own `pyproject.toml`/`setup.cfg`466 config over the generic default, and note the override applied.467468## Constraints469470- **Architecture is invariant**: the project's fixed structure is the stable471 base. Never break it, bypass it, or replace it with a different layout while472 coding. Add and change code *within* the architecture; keep it clear.473- Single responsibility: this skill ONLY governs research-code standards474 (architecture, naming, structure, configs); do not mix in unrelated tasks.475- It is a **contextual enforcer**, not a post-hoc reviewer: apply conventions476 as code is written/edited, not after.477- Two axes only: (1) project-level architecture, (2) code-level naming/format/478 calling. Keep both uniform; do not introduce a third, ad-hoc concern.479- Never auto-commit or push changes unless the user explicitly asks.480- Never invent config values or names; derive them from the conventions and481 existing project patterns.482- Respect the project's existing line-length / formatter config if present.483- Load reference docs lazily: read `references/` files only for the concern484 being acted on, not all at once.485- Use the unified rule-code registry in `references/coordination.md`; never486 invent a code not in the registry, and never apply one rule under two codes.487