Skip to main content
The grammar is the normative description of every construct in skill.spec.yml. YAML is the interchange format; the grammar describes the conceptual tree independent of YAML spelling. v0 is deliberately not a programming language — it is a structured skill contract that expresses routes, rules, elicitations, states, commands, imports, resources, code, artifacts, recipes, snippets, closures, tests, and proof hooks without becoming an execution engine.

Document Structure

Every skill.spec.yml follows the top-level skillspec production:
The header is the only mandatory section. Every valid spec must include all four fields.
activation provides hints a harness uses to decide whether to load the skill before reading the full spec. It does not execute routing.
Routes are named strategies. Lower rank means earlier default preference unless a rule overrides it.
Rules match task signals and adjust route, forbids, elicitations, and post-success actions. Rules are evaluated in file order.
Elicitations ask a specific bounded question instead of an open-ended one. Choices may set facts, steer a route, or advance to a state.
trace declares which decision events should be persisted by an evaluator or harness.
Declare required tools, runtime-loadable guidance, provenance material, executable knowledge, data products, and structured procedures respectively.
States are named lifecycle positions. Commands are instruction templates. Snippets are user-facing prose. Closures describe post-task behavior.
proof.metrics names the measures the policy is improving. tests are scenario contracts. review_required lists items that need human review. metadata is an open mapping.

Identifiers

All named constructs in a spec use the identifier production:
Valid examples: browser, local_cli, check-auth, task.router Identifiers are stable API. They are what tests, compilers, and importing tools refer to. Human labels (like route.label or rule.reason) can change freely; identifiers should not churn because renaming one breaks every test, import, and cross-reference that names it.
Identifiers must start with a lowercase letter. Digits, underscores, hyphens, and dots are allowed after the first character. Uppercase, spaces, and other punctuation are not valid.
The header section is mandatory. A spec is invalid without all four fields:

Activation

activation and applies_when are harness-selection hints. A harness may use them to decide whether to load the skill, but they are not part of route decision logic.
activation.summary should be placed at the start of generated frontmatter descriptions so a harness can choose the skill before loading the full spec. activation.keywords widens the selection surface without changing route decision. activation.priority is advisory metadata for humans and harnesses.

Routes

Routes are candidate ways to satisfy work. They do not execute anything by themselves.

Rules

Rules are the steering layer. They are evaluated in file order; effects are additive except prefer (which replaces the selected route) and route_order (which replaces the current order).
Predicate fields (all compose with logical AND; values within user_says_any compose with logical OR): Rule effect algebra — for each matching rule:
Every route-changing, forbid-heavy, or elicitation-producing rule should have at least one scenario test. A rule without a test is only structured prose.

Elicitations

Elicitations are bounded questions — used when the skill should ask for a specific missing decision rather than guessing or asking an open-ended question.
Choices may set facts (sets), steer a route (route), or advance to a state (next). They do not execute commands by themselves. required_when conditions fire when a specific route is selected, a fact is missing, or a predicate matches. default must reference one of the declared choice ids.
When authoring YAML by hand, quote question strings that contain : or use a block scalar (|). An unquoted string like question: What are we reviewing: a dependency list? will be parsed as a broken mapping before SkillSpec validation runs.

Trace

trace declares which decision events should be persisted by an evaluator or harness. The spec describes the contract; the evaluator writes the events.
Only one mode exists in v0: event_log. If record is empty or absent, a conforming evaluator may record every v0 event kind. If required is true, a conforming harness should either write the trace or state that tracing is unavailable before relying on the decision.

Tests

Tests are scenario contracts. Every meaningful route rule should have at least one scenario.
An expectation must contain at least one assertion. The three assertion families are:

Proof

proof.metrics names the measures the policy is trying to improve:
Proof metrics are identifiers, not computed values. They give harnesses, CI pipelines, and reviewers a stable vocabulary for what the spec is optimizing.

Validation

skillspec validate <path> performs structural and cross-reference checks on a spec. The key rules enforced:
  • Every Rule.prefer references an existing Route.id
  • Every Rule.elicit item references an existing elicitation
  • Every Elicitation.default references one of its choices
  • Every Test.expect.route references an existing Route.id
  • Every Command.requires.dependencies item references an existing dependency
  • The import dependency graph is acyclic
  • Every on-demand import is connected to the runtime graph
  • Every scenario test declares at least one concrete expectation
Typed v0 objects are strict: unknown fields are invalid. A misspelled field name like prefr: browser or forbit: [native_search] will cause a validation error rather than silently disappearing. This strictness is intentional — behavior that is misspelled is behavior that does not execute.

Minimal Valid Spec

The following is the smallest valid skill.spec.yml, taken from the conformance suite:
This spec defines one route, one rule that selects it, and one scenario test that proves the rule fires. Everything else — activation, trace, commands, dependencies, imports — is optional.