Skip to main content
This document provides a comprehensive overview of Skill Lab’s architecture, including the tech stack, data flow, core components, and design patterns.

Tech Stack

Runtime Dependencies

Development Dependencies

Directory Structure

Data Flow

The following diagram illustrates how data flows through the system during a static evaluation:

Core Components

Data Models (core/models.py)

All models use immutable dataclasses with Python 3.10+ union syntax:

Enumerations

Immutable Data Classes

All data models are immutable (frozen=True) to prevent accidental modifications and ensure thread safety.

Check Registration Pattern

Skill Lab uses a decorator-based auto-discovery pattern for both static checks and trace handlers.

1. Generic Registry Base Class

2. Specialized Check Registry

3. Check Definition

Why This Pattern?

  • Zero manual wiring - Add decorator, checks are auto-discovered
  • Easy testing - registry.clear() for isolation
  • Selective execution - Pass check_ids to run a subset
  • Type safety - Generic base class provides type checking

Two Check Patterns

Skill Lab supports two distinct patterns for defining static checks:

1. Behavioral Checks (Hand-written)

For complex validation logic requiring custom implementation:
Used in:
  • structure.py (7 checks)
  • naming.py (1 check)
  • content.py (11 checks)

2. Schema-Based Checks (Declarative)

For simple field validation using declarative rules:
The _make_schema_check() factory automatically creates check classes from these rules.
When adding new frontmatter fields, update both FRONTMATTER_SCHEMA in schema.py and SPEC_FRONTMATTER_FIELDS in structure.py to keep them in sync.

Scoring Algorithm (core/scoring.py)

Step 1: Calculate Per-Dimension Score

For each dimension:
Weights by severity:
  • ERROR = 1.0
  • WARNING = 0.5
  • INFO = 0.25

Step 2: Calculate Weighted Average

Example Calculation

Parser (parsers/skill_parser.py)

The skill parser handles:
  1. Frontmatter extraction via regex: ^---\n(.*?)^---\n
  2. YAML parsing with custom _SkillYAMLLoader that prevents implicit type coercion
  3. Metadata extraction - pulls name and description fields
  4. Subfolder detection - checks for /scripts, /references, /assets
  5. Graceful error handling - collects errors in parse_errors tuple
The custom YAML loader prevents yes→True, null→None coercion, keeping all values as strings for consistent validation.

Exception Hierarchy (core/exceptions.py)

All custom exceptions extend SkillLabError:
Usage:

CLI Commands

Built with Typer for automatic help generation and type validation:
Evaluation Flags:
  • -V / --verbose: Show all checks, not just failures
  • -s / --spec-only: Only run spec-required checks (10 checks)
  • --suggestions-only: List only quality suggestion checks (18 checks)

Trigger Testing

Trigger testing verifies that skills activate correctly for different prompt types.

Trigger Types

Runtime Adapters

Runtime adapters execute skills and capture traces:
Supported Runtimes:
  • ClaudeRuntime - Executes via claude --print --output-format stream-json
  • CodexRuntime - Executes via codex exec --json --full-auto

Design Decisions

Adding a New Check

See the Contributing Guidelines for detailed instructions on adding new checks. Quick reference:
  1. Create class extending StaticCheck in appropriate checks/static/ module
  2. Define class attributes: check_id, check_name, severity, dimension
  3. Set spec_required = True if required by Agent Skills spec
  4. Implement run(skill: Skill) -> CheckResult
  5. Add @register_check decorator
  6. Add tests to tests/test_checks.py
For schema-based checks, simply add a FieldRule to FRONTMATTER_SCHEMA.