skyl

the standard

Spec

A registry is only as good as what it refuses. This is what a skill has to be, and what a rule has to survive.

Skill format

What a skill file is, and which half of it reaches the model.

A skill is one directory: a SKILL.md, and optional references/.

skills/android/kotlin/
├── SKILL.md
└── references/
    └── cancellation.md

Frontmatter

---
name: android/kotlin          # family/skill, the installable identity
axis: language                # core | language | framework | service | topic
family: android
description: "Kotlin mechanics on Android: coroutine scope and cancellation, flow
  collection, nullability and equality. Use when most of the code is Kotlin."   # quoted: a
                              # plain YAML scalar may not contain a colon followed by a space
requires: [android/core]      # skills that must be installed alongside
version: 1.1.0                # semver; a retirement is a minor bump
authors: [ahmmedrejowan]
agent_sections: [rules]       # which sections an installer gives the agent
retired: [ASYNC-1, TYPE-2]    # rule ids removed, and why, in Provenance
detect:                       # how a project is recognised
  gradle_dependency: ["org.jetbrains.kotlin:kotlin-stdlib"]
---

description is one line, and it is read by both audiences. A person scanning the registry decides from it whether to open the skill; a model deciding whether a skill is relevant reads the same sentence. Say what the skill governs, then when it applies. It is metadata, so adding or rewording one is a patch.

agent_sections is the load-bearing field. The file is written for two readers. An installer gives the agent only the listed sections; everything else, ## Why, ## Pitfalls ## Provenance, is for the human deciding whether to trust the skill. That split is what lets a skill carry its own evidence without spending the agent's context on it.

Versioning

Every skill starts at 1.0.0 when it is first published here. Work before publication happened in a private workspace and its version numbers were internal bookkeeping, not a release history, so they are not carried over.

After publication, semver applies to what an installer receives:

change bump
a rule retired, added, or its instruction changed minor
wording, Why, Pitfalls, Provenance, references patch
a rule id renamed, or requires changed major
detect widened or narrowed minor

Evidence is anchored to evals, not to versions, because the evals are published and the pre-publication versions were not. A ## Provenance entry says "eval 19 measured all four", never "v1.3.0 added".

detect keys are family-defined and resolved by the index. Current keys: gradle_dependency gradle_plugin, file, manifest_element, manifest_attribute.

Sections

section audience required
## Rules the agent yes
## Why the human yes for a shipped skill
## Pitfalls the human yes for a shipped skill
## Provenance the human yes for a shipped skill

A rule

Three parts, always:

- **ASYNC-4** `must`: A read that can be re-triggered, a query, a filter, a refresh, is
  cancelled by the operator built for it, not by tracking jobs by hand.
  *Why:* hand-tracked jobs race their own cancellation on fast input. And cancelling a write does
  not un-send it, the request may already have reached the server.
  *Not when:* every emission must be processed, where the operator is losing work by design.

A decidable instruction. Not "use flows appropriately", a reader must be able to look at a file and say yes or no. Undecidable text is unfalsifiable, and unfalsifiable text is unactionable.

A Why that names the failure not the principle. The reader has to be able to recognise the bug in the wild.

A Not when. Almost nobody writes these, and their absence is what turns a rules file into a nitpick generator. A rule without a stated boundary gets applied everywhere.

Rule ids

PREFIX-N, stable for the life of the skill. Ids are never reused. A retired rule's id is listed in retired: and stays retired, because published evidence and cross-references point at it.

Priority

must, the failure is silent, expensive, or hard to reverse. should, real exceptions exist, and the rule says to name yours.

Cross-references

A rule may cite another skill's rule as `android/core WORK-3`. Every such reference is resolved by scripts/xrefcheck.py in CI; a reference to a rule that does not exist fails the build. Layers must not restate each other, see METHOD.md.

FORMAT.md on GitHub

The axes

Five of them. A rule belongs to exactly one.

A skill belongs to exactly one axis. The axis determines when it loads.

axis loads when examples
core always, for the family android/core
language the language is present android/kotlin, android/java
framework the UI toolkit or framework is present android/compose, android/xml
service an external service is used appwrite/core (not yet built)
topic a concern only some projects have android/db, android/permissions

A project loads the intersection: its core, its language, its framework, whichever services it calls, and whichever topics it actually has.

The core / topic boundary

Core is what every project in the family has. A topic is what only some have which is exactly what makes a topic detectable.

If a rule would fire on every project, it belongs in core and needs no detection. If it fires on some, it is a topic and the detect block is what decides.

Topics group by concern, not by library

android/db covers persistence, what is stored, what survives, what is encrypted at rest, whether the project uses Room, DataStore, or files. It is not android/room.

The test: does this say something the library's own documentation does not? A skill organised around a library tends to restate that library's docs, which is the material the model already has.

What is not an axis

Architecture patterns (mvi, clean) are not skills: nothing detects them. They resolve to a set of skills, core + kotlin + compose, and are better expressed as a stack template.

A concern with no detection signal is a references/ file inside the skill that owns it, not a skill of its own.

Family

A family is a platform or ecosystem: android, web, appwrite. Families compose sideways, a project can load android/* and appwrite/* together, which is why service is its own axis rather than a topic inside each platform.

AXES.md on GitHub

Admission

The four tests a rule has to pass to be published.

A rule ships only if it passes all four tests, in order.

1. Does the model get this wrong unprompted?

The first test, and the one that outranks correctness. A rule the model already follows costs context and displaces one that would have worked.

This is decided by running the task with no skill loaded and reading what comes out. Not by judgement, and not by how important the rule feels.

Rules have been dropped against this test, including ones that felt obviously right. The in-context permission-timing rule is the most-repeated advice in the permissions corpus, and no control run of twelve got it wrong.

2. Does a linter or the compiler already catch it?

Most of a style guide is already a compiler error, a lint warning, or something the formatter fixes. A published survey of agent context files found 62% carrying rules a linter already enforces occupying context for nothing.

3. Would 900 of 1000 projects hit it?

Not 1 in 1000. Interesting is not the bar.

How not to score this test: by asking whether the situation is possible. Almost anything is possible. Ask whether a project that never thinks about this ships the bug, and whether the person writing the code would recognise it.

4. Is it checkable at every token, or a deferred action?

Constraints that describe a property of the artifact hold under load. Constraints that defer an action to a later moment drop sharply, while fully visible in context the whole time.

GOOD  (a property of the artifact)
  Money is a 64-bit integer of minor units plus a currency code, never a float.

BAD   (an action deferred to later)
  Remember to add a migration when you change the schema.

Both are true. Only the first is a rule. No skill in this registry carries a checklist because a deferred action stated as a rule is dropped at exactly the moment it matters.


A rule lives in a capability window

A rule earns its slot between two bounds. Above the window the model already does it; below the window the model cannot act on it even when told.

Both bounds are real and measured:

rule Opus Sonnet Haiku
core STATE-1 save state for process death 6/6 unaided 0/2 → 2/2 0/2 → 2/2
core STATE-4 input owned by the control 0/6 → 6/6 0/2 → 1/2 0/2 → 0/2

STATE-1 is the rule that curating against the frontier alone would have deleted: the strongest model does not need it, and two of three do. STATE-4 is the inverse, it separates only on the model capable of acting on it.

So a rule is not admitted or retired globally. It is admitted for a window, and the registry records which models were tested.

Corpus support is an anti-signal

The material a rule could be drawn from and the material the model was trained on are the same material. The more repositories document a practice, the more likely the model already follows it.

Measured repeatedly, including within a single skill: the rules with zero corpus support were the entire measured effect, while the corpus-backed rules in the same file were satisfied by every arm. Across six axes, register size has predicted result thinness rather than richness, the largest register in the project (238 claims) produced the smallest skill (3 rules).

Every confirmed result here came from a control arm or a primary source. None came from corpus frequency.

What the evidence covers

Every skill here was measured: drafted from a claim register, checked against primary sources, and put in front of control and treated arms across four model families. What separated is recorded in evidence/, skill by skill, including the results that went the other way.

An eval task is a spot check, not a proof. These tasks are small and self-contained so a run finishes in minutes and a difference is attributable. A real project is larger, has more context competing for the model's attention, and compounds a mistake across many files. A rule that moves a small task by one run moves a real codebase by considerably more, and a rule that a small task cannot tempt is not thereby unnecessary.

So the evidence is read as: this is what we could demonstrate under controlled conditions, and the effect in a real project is larger rather than smaller.

ADMISSION.md on GitHub