RFC-002: wsn-lint
This RFC specifies wsn-lint, a static analysis tool that mechanically enforces Weyl Standard Nix.
RFC-002: wsn-lint
| Field | Value |
|---|---|
| RFC | 002 |
| Title | wsn-lint — Machine-Checkable Weyl Standard Nix |
| Author | Weyl AI Infrastructure Team |
| Status | Draft |
| Created | 2025-01-05 |
| Requires | RFC-001 |
Abstract
This RFC specifies wsn-lint, a static analysis tool that mechanically enforces
Weyl Standard Nix. The tool uses hnix for parsing and AST analysis, enabling most
RFC-001 requirements to be checked without evaluation.
Motivation
A specification without enforcement is a suggestion. RFC-001 establishes normative requirements, but compliance currently depends on code review.
Specification
Error Levels
| Level | Meaning |
|---|---|
| ERROR | Non-conformant, CI must fail |
| WARNING | Review required |
| INFO | Suggestion |
AST Rules (No Evaluation Required)
WSN-E001: with-statement
Level: ERROR
# ERRORwith lib;{ options.foo = mkOption { }; }
# OK (list context exception)environment.systemPackages = with pkgs; [ vim git ];WSN-E002: rec-in-derivation
Level: ERROR
# ERRORstdenv.mkDerivation rec { version = "1.0"; }
# OKstdenv.mkDerivation (finalAttrs: { version = "1.0"; })WSN-E003: non-lisp-case
Level: ERROR
Identifiers in weyl.* namespaces using camelCase or snake_case.
WSN-E004: missing-class
Level: ERROR
Files in nix/modules/(nixos|darwin|home)/ without _class attribute.
WSN-E005: default-nix-in-packages
Level: ERROR
# ERRORnix/packages/my-tool/default.nix
# OKnix/packages/my-tool.nixWarnings
WSN-W001: rec-anywhere
Level: WARNING
Flag all rec attrsets for review.
WSN-W002: if-in-module-config
Level: WARNING
if/then/else inside module config blocks.
WSN-W003: long-inline-string
Level: WARNING
Multi-line strings exceeding 10 lines.
WSN-W004: missing-meta
Level: WARNING
Derivation builder calls without meta attribute.
WSN-W005: missing-description
Level: WARNING
mkOption calls without description attribute.
Import Graph Rules (Requires Resolution)
WSN-E010: external-nixpkgs-config
Level: ERROR
# ERRORpkgs = import inputs.nixpkgs { config.cudaSupport = true; };
# OKpkgs = inputs.weyl-std.nixpkgs.${system};WSN-E011: nixpkgs-config-in-nixos
Level: ERROR
Assignment to nixpkgs.config.* in NixOS configuration files.
Usage
# Check current directorywsn-lint check .
# Check flakewsn-lint check --flake .
# Auto-fix where possiblewsn-lint fix .
# JSON output for CIwsn-lint check --format json .Exit Codes
| Code | Meaning |
|---|---|
| 0 | Conformant |
| 1 | Errors found |
| 2 | Warnings only (with —strict) |
Implementation
wsn-lint uses hnix for parsing:
import Nix.Parser (parseNixFileLoc)import Nix.Expr.Types
checkWithStatement :: NExprLoc -> [Diagnostic]checkWithStatement expr = case expr of NWith _ _ body -> [Error "WSN-E001" (spanOf expr) "with statement"] _ -> []CI Integration
- name: wsn-lint run: | nix run github:weyl-ai/wsn-lint -- check --flake .Future Work
- IDE integration (LSP)
- Auto-fix for more patterns
- Custom rule definitions