Adding a New Rule
SkillDev toolsUse when adding a new ryl lint rule or changing an existing rule's wiring. Walks the multi-site checklist (rule module, registration, dispatch, TOML config, tests, docs) where a missed site usually trips a guard test rather than shipping silently.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Adding a New Rule skill
What this skill tells your AI
The instructions your AI receives, as published by owenlamont/ryl in .agents/skills/adding-a-rule/SKILL.md and read by ahel’s review.
A rule touches several disconnected sites; a missing one usually fails a guard test
rather than shipping silently. Work this checklist (the property-tests and
coverage dev skills expand steps 5–6):
- Rule module
src/rules/<rule>.rs: apub const ID, aConfigwithresolve(&YamlLintConfig), acheck(...) -> Vec<Violation>(orOption), and aViolation { line, column, message }. Open with a//!header — one-line purpose, aSources:line (spec / yamllint / authoritative refs), and the "no safe--fix" note where applicable. Prefer granit scanner/event tokens over char heuristics; if the rule tracks key/value position, advance the sharedsupport::mapping_key_walker::Walkeron every node event, includingEvent::Alias(Walker::skip_node), or key/value alternation desyncs. - Register in
src/rules/mod.rs:pub mod <rule>;plus theIDinALL_RULE_IDS— and inRYL_ONLY_RULE_IDSwhen yamllint has no equivalent (that reserves it to TOML config; see the YAML-vs-TOML note inAGENTS.md). - Dispatch: one
lint_rule!(...)call insrc/lint.rs, in the right reported-order slot of the matching batch fn (collect_layout/collect_value/collect_block_diagnostics). Pick the arm matching the rule's shape (config or not,Vec/Option, per-violation or fixedMESSAGE). - TOML config wiring (
src/config_schema.rs+config_schema/serialization.rs): aRuleNamevariant +as_strarm, aRulesTablefield with its…Optionstype, and theinsert_serializedline inrules_table_to_value. These four parallel lists have no compile-time cross-check; theevery_rule_round_trips_through_toml_serializationguard test catches a forgotten serialization line. Regenerate the committedryl.{toml,yaml}.schema.json(see thetesting-trapsdev skill) and runprek. - Tests: add the rule to
property_check'scollect_spans+ aRULE_TRIGGERSrow; if it has a safe--fix, alsoSAFE_FIX_RULESand the safe-fix generator. Add a CLI testtests/cli_<rule>_rule.rs(use the sharedcommon::cliharness) and an embedded-markdown regression test intests/cli_markdown_embed.rs. - Docs: a
docs/rules/<rule>.mdpage + the index, and a "How ryl differs from yamllint" entry for any deliberate divergence. When a doc page shows example CLI output, produce theline:col/message by running ryl on the shown input — not by hand (hand-written examples have shipped with wrong columns).
granit event/span gotchas (granit-parser 0.0.5)
Facts the codebase relies on; re-verify on a granit bump:
- Derive a token's position from
marker.byte_offset()viacrate::rules::support::span_utils(the pattern every span-using rule follows), rather than reading offsets off the rawSpanby hand. - Any rule reading granit token/event line numbers must index lines split the
granit-aligned way (
\r\n|\r|\n, vialine_syntax), never\n-only: a bare\ris a line break to granit, so a\n-only split desyncs and can panic out-of-bounds. - For an indentation/column-sensitive rule, derive structure from granit events from the
start; a line-based
classify_mappingis YAML-unsound on colons-in-scalars, quoted escapes, and multiline plain scalars (the comments-indentation rewrite learned this over ~5 review rounds). - Matching a core-schema tag (
!!int, …): usecrate::yaml_dom::core_schema_suffix/is_core_schema, never granit's handle-onlyTag::is_yaml_core_schema(a verbatim!<tag:yaml.org,2002:int>slips past it); compare the full resolved URI when a%TAGcan split it, assupport::merge_keydoes.
Signals
- GitHub stars
- 72
- Forks
- 3
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
adding-a-rule- Source
- github.com/owenlamont/ryl