{
  "$schema": "registry.schema.json",
  "specification": "OpenLint Ruleset Specification",
  "version": "draft",
  "line": 1,
  "label": "Working Draft 1.x",
  "generated": "2026-10-22",
  "classes": [
    {
      "id": "/conf/ruleset-core",
      "name": "ruleset-core",
      "target": "ruleset",
      "depends": [],
      "members": [
        "/req/ruleset/document",
        "/req/ruleset/single-document",
        "/req/ruleset/schema",
        "/rec/rules/reserved-names",
        "/req/shorthands/inherited-only",
        "/req/aliases/no-cycle",
        "/rec/custom-functions/prefer-core",
        "/req/given/alias-defined",
        "/req/then/function-known",
        "/req/then/function-options-valid",
        "/per/extension-properties/anywhere"
      ],
      "tests": [
        "/conf/aliases/chain",
        "/conf/aliases/cycle",
        "/conf/aliases/name",
        "/conf/aliases/name-valid",
        "/conf/aliases/scoped-form-missing-formats",
        "/conf/aliases/scoped-form-valid",
        "/conf/aliases/simple-form-string",
        "/conf/aliases/simple-form-valid",
        "/conf/custom-functions/declaration-not-array",
        "/conf/custom-functions/declaration-valid",
        "/conf/extends/entry-forms-valid",
        "/conf/extends/entry-invalid-mode",
        "/conf/extends/entry-tuple-length",
        "/conf/extends/shape-array",
        "/conf/extends/shape-object",
        "/conf/extends/shape-string",
        "/conf/extension-properties/accepted",
        "/conf/formats/shape-string",
        "/conf/formats/shape-valid",
        "/conf/formats/unknown-identifier",
        "/conf/given/alias-declared",
        "/conf/given/alias-redefined-both",
        "/conf/given/alias-redefined-own",
        "/conf/given/alias-undefined",
        "/conf/given/bare-property-name",
        "/conf/given/path-expression-forms",
        "/conf/given/present",
        "/conf/given/required",
        "/conf/given/shape-empty-array",
        "/conf/given/shape-object",
        "/conf/given/shape-valid",
        "/conf/overrides/file-scoped-empty",
        "/conf/overrides/file-scoped-valid",
        "/conf/overrides/mixed-globs",
        "/conf/overrides/pointer-scoped-extends",
        "/conf/overrides/pointer-scoped-rule-object",
        "/conf/overrides/pointer-scoped-valid",
        "/conf/overrides/shape-empty",
        "/conf/overrides/shape-no-files",
        "/conf/overrides/shape-valid",
        "/conf/parser-options/shape-extension-property",
        "/conf/parser-options/shape-unknown-option",
        "/conf/parser-options/shape-unknown-severity",
        "/conf/parser-options/shape-valid",
        "/conf/rule/all-properties",
        "/conf/rule/recommended-not-boolean",
        "/conf/rule/then-present",
        "/conf/rule/then-required",
        "/conf/rule/type-unknown",
        "/conf/rule/unknown-property",
        "/conf/ruleset/all-properties",
        "/conf/ruleset/contributes-empty",
        "/conf/ruleset/contributes-extends-only",
        "/conf/ruleset/description-not-string",
        "/conf/ruleset/document-json",
        "/conf/ruleset/document-object",
        "/conf/ruleset/document-root-array",
        "/conf/ruleset/document-single-yaml-document",
        "/conf/ruleset/document-syntax-error",
        "/conf/ruleset/document-two-yaml-documents",
        "/conf/ruleset/documentation-url-intranet",
        "/conf/ruleset/documentation-url-invalid",
        "/conf/ruleset/documentation-url-mailto",
        "/conf/ruleset/extension-root-property",
        "/conf/ruleset/rules-not-object",
        "/conf/ruleset/unknown-root-property",
        "/conf/severity/values-invalid",
        "/conf/severity/values-name",
        "/conf/severity/values-number",
        "/conf/shorthands/inherited",
        "/conf/shorthands/not-inherited",
        "/conf/shorthands/numeric",
        "/conf/shorthands/unknown-name",
        "/conf/shorthands/values-valid",
        "/conf/then/function-core",
        "/conf/then/function-missing",
        "/conf/then/function-unknown",
        "/conf/then/invocation-form-valid",
        "/conf/then/options-not-object",
        "/conf/then/options-on-no-option-function",
        "/conf/then/options-required-missing",
        "/conf/then/options-unknown-value",
        "/conf/then/options-valid",
        "/conf/then/shape-empty-array",
        "/conf/then/shape-string",
        "/conf/then/shape-valid"
      ],
      "text": "The ruleset format: what a ruleset document has to look like to be loaded by any conforming linter. Most of it is one requirement, validity against the ruleset schema. The other requirements are constraints a schema cannot express."
    },
    {
      "id": "/conf/linter-core",
      "name": "linter-core",
      "target": "linter",
      "depends": [
        "ruleset-core"
      ],
      "members": [
        "/req/document/any-root",
        "/req/document/encoding",
        "/req/parsing/syntax-error",
        "/req/parsing/several-documents",
        "/req/parser-options/duplicate-keys",
        "/req/parser-options/incompatible-values",
        "/req/resolution/local",
        "/req/resolution/external",
        "/req/resolution/cycle",
        "/req/resolution/unresolvable",
        "/req/linter/reject-invalid",
        "/req/linter/accept-valid",
        "/req/extends/load",
        "/req/extends/unresolvable",
        "/req/extension-properties/ignored",
        "/req/overrides/scope",
        "/req/overrides/order",
        "/req/overrides/extends",
        "/req/overrides/aliases",
        "/req/overrides/reject-foreign-property",
        "/req/overrides/reject-unknown-shorthand",
        "/req/overrides/reject-undeclared-alias",
        "/req/overrides/checked-when-applied",
        "/req/overrides/pointer-scope",
        "/req/severity/numeric-equivalence",
        "/req/severity/default",
        "/req/rules/recommended",
        "/req/extends/mode-recommended",
        "/req/extends/mode-all",
        "/req/extends/mode-off",
        "/req/extends/order",
        "/req/rules/redefinition-merge",
        "/req/shorthands/severity",
        "/req/shorthands/false",
        "/req/shorthands/true",
        "/req/severity/off",
        "/req/formats/identifiers",
        "/req/formats/detection-scope",
        "/req/formats/rule-scope",
        "/req/formats/ruleset-default",
        "/req/formats/rule-overrides-ruleset",
        "/req/formats/unscoped-runs-everywhere",
        "/req/formats/unrecognized-document",
        "/req/given/evaluate",
        "/req/given/no-match",
        "/req/given/resolved",
        "/req/given/jsonpath",
        "/req/given/once-per-node",
        "/req/given/alias-expansion",
        "/req/aliases/compose",
        "/req/aliases/scoped",
        "/req/then/apply-each",
        "/req/then/field",
        "/req/then/field-key",
        "/req/then/function-options",
        "/req/result/fields",
        "/req/result/code",
        "/req/result/severity",
        "/req/result/range",
        "/req/result/source",
        "/req/result/order",
        "/req/result/reference-target",
        "/rec/result/documentation-url",
        "/req/message/override",
        "/req/message/placeholders",
        "/req/message/default",
        "/req/functions/input-types",
        "/req/functions/truthy",
        "/req/functions/falsy",
        "/req/functions/defined",
        "/req/functions/undefined",
        "/req/functions/pattern",
        "/req/functions/casing",
        "/req/functions/length",
        "/req/functions/alphabetical",
        "/req/functions/enumeration",
        "/req/functions/schema",
        "/req/functions/xor",
        "/req/functions/or",
        "/req/functions/unreferenced-reusable-object"
      ],
      "tests": [
        "/conf/aliases/compose",
        "/conf/aliases/scoped-last-target",
        "/conf/aliases/scoped-no-target",
        "/conf/aliases/scoped-oas2",
        "/conf/aliases/scoped-oas3",
        "/conf/document/empty-file",
        "/conf/document/root-array",
        "/conf/document/utf8-keys",
        "/conf/extends/base-invalid",
        "/conf/extends/load",
        "/conf/extends/mode-all",
        "/conf/extends/mode-all-extra-element",
        "/conf/extends/mode-default",
        "/conf/extends/mode-off",
        "/conf/extends/mode-recommended",
        "/conf/extends/precedence",
        "/conf/extends/precedence-order",
        "/conf/extends/redefine-keeps-properties",
        "/conf/extends/resolvable",
        "/conf/extends/unresolvable",
        "/conf/extension-properties/ignored",
        "/conf/formats/detect-aas2-6",
        "/conf/formats/detect-aas2-needs-patch",
        "/conf/formats/detect-arazzo",
        "/conf/formats/detect-json-schema-2020-12",
        "/conf/formats/detect-json-schema-loose",
        "/conf/formats/detect-number-version",
        "/conf/formats/detect-oas2",
        "/conf/formats/detect-oas3-1",
        "/conf/formats/detection-declared-only",
        "/conf/formats/rule-overrides-ruleset",
        "/conf/formats/rule-scope",
        "/conf/formats/ruleset-default",
        "/conf/formats/unrecognized-document",
        "/conf/formats/unrecognized-unscoped",
        "/conf/formats/unscoped",
        "/conf/functions/alphabetical",
        "/conf/functions/alphabetical-case",
        "/conf/functions/alphabetical-keyed-by",
        "/conf/functions/alphabetical-numbers",
        "/conf/functions/casing",
        "/conf/functions/casing-non-ascii",
        "/conf/functions/casing-types",
        "/conf/functions/defined",
        "/conf/functions/enumeration",
        "/conf/functions/enumeration-types",
        "/conf/functions/falsy",
        "/conf/functions/input-types",
        "/conf/functions/length",
        "/conf/functions/length-code-units",
        "/conf/functions/length-min",
        "/conf/functions/or",
        "/conf/functions/or-null",
        "/conf/functions/pattern",
        "/conf/functions/schema",
        "/conf/functions/schema-absent",
        "/conf/functions/schema-all-errors",
        "/conf/functions/schema-default-draft",
        "/conf/functions/schema-dialect",
        "/conf/functions/schema-first-error",
        "/conf/functions/schema-format",
        "/conf/functions/schema-ref",
        "/conf/functions/truthy",
        "/conf/functions/undefined",
        "/conf/functions/unreferenced-reusable-object",
        "/conf/functions/xor",
        "/conf/functions/xor-null",
        "/conf/given/alias-expansion",
        "/conf/given/evaluate-all-matches",
        "/conf/given/evaluate-multiple-expressions",
        "/conf/given/jsonpath-filter",
        "/conf/given/match",
        "/conf/given/no-match",
        "/conf/given/once-per-node",
        "/conf/given/resolved-default",
        "/conf/given/resolved-false",
        "/conf/linter/accept-valid",
        "/conf/linter/reject-invalid",
        "/conf/linter/walkthrough",
        "/conf/message/default-description",
        "/conf/message/override",
        "/conf/message/placeholder-description",
        "/conf/message/placeholder-path",
        "/conf/message/placeholder-property",
        "/conf/overrides/aliases-existing-rule",
        "/conf/overrides/aliases-new-rule",
        "/conf/overrides/aliases-outside-globs",
        "/conf/overrides/extends",
        "/conf/overrides/extends-with-rules",
        "/conf/overrides/extends-without-rules",
        "/conf/overrides/order",
        "/conf/overrides/pointer-scope",
        "/conf/overrides/pointer-scope-at",
        "/conf/overrides/redefined-rule-alias-applied",
        "/conf/overrides/redefined-rule-alias-declared",
        "/conf/overrides/scope-match",
        "/conf/overrides/scope-no-match",
        "/conf/overrides/scope-outside-ruleset-directory",
        "/conf/overrides/scope-ruleset-directory",
        "/conf/overrides/unknown-property-applied",
        "/conf/overrides/unknown-property-not-applied",
        "/conf/parser-options/duplicate-keys-default",
        "/conf/parser-options/duplicate-keys-off",
        "/conf/parser-options/duplicate-keys-warn",
        "/conf/parser-options/incompatible-values",
        "/conf/parsing/several-documents",
        "/conf/parsing/syntax-error",
        "/conf/resolution/cycle",
        "/conf/resolution/external",
        "/conf/resolution/local",
        "/conf/resolution/shared-reference",
        "/conf/resolution/unresolvable",
        "/conf/resolution/unresolvable-kept",
        "/conf/result/code",
        "/conf/result/fields",
        "/conf/result/order",
        "/conf/result/range",
        "/conf/result/range-utf16",
        "/conf/result/severity",
        "/conf/result/source",
        "/conf/rules/recommended-default",
        "/conf/rules/recommended-false",
        "/conf/severity/default",
        "/conf/severity/numeric-equivalence",
        "/conf/severity/off",
        "/conf/severity/off-control",
        "/conf/severity/result",
        "/conf/shorthands/false",
        "/conf/shorthands/false-control",
        "/conf/shorthands/override-own-rule",
        "/conf/shorthands/override-unknown",
        "/conf/shorthands/override-unknown-not-applied",
        "/conf/shorthands/severity",
        "/conf/shorthands/true-enables",
        "/conf/shorthands/true-keeps-severity",
        "/conf/shorthands/true-off",
        "/conf/then/apply-each",
        "/conf/then/apply-each-problem",
        "/conf/then/field",
        "/conf/then/field-jsonpath",
        "/conf/then/field-key",
        "/conf/then/field-missing",
        "/conf/then/field-path",
        "/conf/then/function-options"
      ],
      "text": "Everything a linter does with a ruleset and a document: loading, parsing and resolution, rule state, selecting documents and nodes, applying functions, and the results and messages it reports. It depends on ruleset-core because a linter rejects a ruleset that does not conform to that class. #loading says how."
    },
    {
      "id": "/conf/linter-custom-functions",
      "name": "linter-custom-functions",
      "target": "linter",
      "depends": [
        "linter-core"
      ],
      "members": [
        "/req/custom-functions/missing",
        "/req/custom-functions/invoke",
        "/req/custom-functions/problem-path",
        "/req/custom-functions/no-problems"
      ],
      "tests": [
        "/conf/custom-functions/invoke",
        "/conf/custom-functions/missing",
        "/conf/custom-functions/present",
        "/conf/custom-functions/problem-path",
        "/conf/custom-functions/returns-nothing"
      ],
      "text": "The contract of custom functions, in any language: how a linter resolves a function a ruleset names, calls it, and reports what it returns. A linter claims it together with a binding."
    },
    {
      "id": "/conf/linter-custom-functions-javascript",
      "name": "linter-custom-functions-javascript",
      "target": "linter",
      "depends": [
        "linter-custom-functions"
      ],
      "members": [
        "/req/custom-functions/javascript-load",
        "/req/custom-functions/javascript-promise"
      ],
      "tests": [
        "/conf/custom-functions/javascript-promise",
        "/conf/custom-functions/load-custom-dir",
        "/conf/custom-functions/load-default-dir"
      ],
      "text": "The JavaScript binding of custom functions: how a custom function is written as a JavaScript module, and where a linter finds it."
    }
  ],
  "requirements": [
    {
      "id": "/req/ruleset/document",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "ruleset-document",
      "tests": [
        "/conf/ruleset/document-json",
        "/conf/ruleset/document-object",
        "/conf/ruleset/document-syntax-error"
      ],
      "text": "A ruleset MUST be a JSON RFC8259 or YAML YAML-1.2.2 document."
    },
    {
      "id": "/req/ruleset/single-document",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "proposed",
      "since": "draft",
      "section": "ruleset-document",
      "tests": [
        "/conf/ruleset/document-single-yaml-document",
        "/conf/ruleset/document-two-yaml-documents"
      ],
      "text": "A ruleset written in YAML MUST contain exactly one YAML document."
    },
    {
      "id": "/req/ruleset/schema",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "ruleset-document",
      "tests": [
        "/conf/aliases/name-valid",
        "/conf/aliases/scoped-form-valid",
        "/conf/aliases/simple-form-valid",
        "/conf/aliases/name",
        "/conf/aliases/scoped-form-missing-formats",
        "/conf/aliases/simple-form-string",
        "/conf/custom-functions/declaration-valid",
        "/conf/custom-functions/declaration-not-array",
        "/conf/extends/entry-forms-valid",
        "/conf/extends/entry-tuple-length",
        "/conf/extends/shape-array",
        "/conf/extends/shape-string",
        "/conf/extends/entry-invalid-mode",
        "/conf/extends/shape-object",
        "/conf/formats/shape-valid",
        "/conf/formats/shape-string",
        "/conf/formats/unknown-identifier",
        "/conf/given/path-expression-forms",
        "/conf/given/present",
        "/conf/given/shape-valid",
        "/conf/given/bare-property-name",
        "/conf/given/required",
        "/conf/given/shape-empty-array",
        "/conf/given/shape-object",
        "/conf/overrides/file-scoped-valid",
        "/conf/overrides/mixed-globs",
        "/conf/overrides/pointer-scoped-valid",
        "/conf/overrides/shape-valid",
        "/conf/overrides/file-scoped-empty",
        "/conf/overrides/pointer-scoped-extends",
        "/conf/overrides/pointer-scoped-rule-object",
        "/conf/overrides/shape-empty",
        "/conf/overrides/shape-no-files",
        "/conf/parser-options/shape-valid",
        "/conf/parser-options/shape-extension-property",
        "/conf/parser-options/shape-unknown-option",
        "/conf/parser-options/shape-unknown-severity",
        "/conf/rule/all-properties",
        "/conf/rule/then-present",
        "/conf/rule/recommended-not-boolean",
        "/conf/rule/then-required",
        "/conf/rule/type-unknown",
        "/conf/rule/unknown-property",
        "/conf/ruleset/all-properties",
        "/conf/ruleset/contributes-extends-only",
        "/conf/ruleset/extension-root-property",
        "/conf/ruleset/contributes-empty",
        "/conf/ruleset/description-not-string",
        "/conf/ruleset/document-root-array",
        "/conf/ruleset/documentation-url-intranet",
        "/conf/ruleset/documentation-url-invalid",
        "/conf/ruleset/documentation-url-mailto",
        "/conf/ruleset/rules-not-object",
        "/conf/ruleset/unknown-root-property",
        "/conf/severity/values-name",
        "/conf/severity/values-number",
        "/conf/severity/values-invalid",
        "/conf/shorthands/values-valid",
        "/conf/shorthands/numeric",
        "/conf/shorthands/unknown-name",
        "/conf/then/invocation-form-valid",
        "/conf/then/shape-empty-array",
        "/conf/then/shape-valid",
        "/conf/then/function-missing",
        "/conf/then/options-not-object",
        "/conf/then/shape-string"
      ],
      "text": "The root value of a ruleset MUST be valid against the ruleset schema of this version of this specification, as JSON Schema 2020-12 JSON-SCHEMA-CORE-2020-12 JSON-SCHEMA-VALIDATION-2020-12 defines validity."
    },
    {
      "id": "/rec/rules/reserved-names",
      "kind": "recommendation",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "rules",
      "tests": [],
      "text": "A rule name SHOULD NOT be one of the codes a linter uses for the results it produces itself: parser, unrecognized-format, and invalid-ref."
    },
    {
      "id": "/req/shorthands/inherited-only",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "shorthands",
      "tests": [
        "/conf/shorthands/inherited",
        "/conf/shorthands/not-inherited"
      ],
      "text": "A shorthand in the root rules MUST name a rule the ruleset inherits through extends."
    },
    {
      "id": "/req/aliases/no-cycle",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "aliases",
      "tests": [
        "/conf/aliases/chain",
        "/conf/aliases/cycle"
      ],
      "text": "An alias MUST NOT refer to itself, directly or through other aliases."
    },
    {
      "id": "/rec/custom-functions/prefer-core",
      "kind": "recommendation",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "functions-declaration",
      "tests": [],
      "text": "A ruleset SHOULD use the core functions where they express the assertion, and name a custom function only for an assertion they cannot express."
    },
    {
      "id": "/req/given/alias-defined",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "rule-given",
      "tests": [
        "/conf/given/alias-declared",
        "/conf/given/alias-redefined-both",
        "/conf/given/alias-redefined-own",
        "/conf/given/alias-undefined"
      ],
      "text": "An alias reference in a rule MUST name an alias declared under aliases in the ruleset whose rules contain the rule or, for a rule in a file-scoped override, in that override or that ruleset. When the rule redefines a rule inherited through extends, the ruleset that defines the inherited rule MUST declare that alias too."
    },
    {
      "id": "/req/then/function-known",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "rule-then",
      "tests": [
        "/conf/then/function-core",
        "/conf/then/function-unknown"
      ],
      "text": "function MUST name a #core-functions|core function or a custom function declared in functions."
    },
    {
      "id": "/req/then/function-options-valid",
      "kind": "requirement",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "rule-then",
      "tests": [
        "/conf/then/options-valid",
        "/conf/then/options-on-no-option-function",
        "/conf/then/options-required-missing",
        "/conf/then/options-unknown-value"
      ],
      "text": "When function names a core function, functionOptions MUST satisfy that function's options in #core-functions: only the options its table lists, with the types listed, every required option present, and no functionOptions at all for a function that takes no options."
    },
    {
      "id": "/per/extension-properties/anywhere",
      "kind": "permission",
      "class": "ruleset-core",
      "target": "ruleset",
      "status": "current",
      "since": "draft",
      "section": "extension-properties",
      "tests": [
        "/conf/extension-properties/accepted",
        "/conf/parser-options/shape-extension-property"
      ],
      "text": "A ruleset MAY have extension properties at its root and on any rule, with any value."
    },
    {
      "id": "/req/document/any-root",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-model",
      "tests": [
        "/conf/document/empty-file",
        "/conf/document/root-array"
      ],
      "text": "A linter MUST lint a document whose root value is not an object, and $ MUST select that root value."
    },
    {
      "id": "/req/document/encoding",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-model",
      "tests": [
        "/conf/document/utf8-keys"
      ],
      "text": "A linter MUST read a document and a ruleset as UTF-8."
    },
    {
      "id": "/req/parsing/syntax-error",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "parsing",
      "tests": [
        "/conf/parsing/syntax-error"
      ],
      "text": "When a document has a syntax error, a linter MUST produce a result with the code parser and the severity error."
    },
    {
      "id": "/req/parsing/several-documents",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "parsing",
      "tests": [
        "/conf/parsing/several-documents"
      ],
      "text": "When a YAML document contains several documents, a linter MUST produce a result with the code parser and the severity error, and MUST lint the first document."
    },
    {
      "id": "/req/parser-options/duplicate-keys",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "parsing",
      "tests": [
        "/conf/parser-options/duplicate-keys-default",
        "/conf/parser-options/duplicate-keys-warn",
        "/conf/parser-options/duplicate-keys-off"
      ],
      "text": "When a document has a duplicate key, a linter MUST produce a result with the code parser and the severity of duplicateKeys, error when it is not set, and MUST NOT produce one when it is off."
    },
    {
      "id": "/req/parser-options/incompatible-values",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "parsing",
      "tests": [
        "/conf/parser-options/incompatible-values"
      ],
      "text": "When a YAML document has a mapping key that is not a string scalar, such as 1, true, or null, a linter MUST produce a result with the code parser and the severity of incompatibleValues, error when it is not set, and MUST NOT produce one when it is off."
    },
    {
      "id": "/req/resolution/local",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "resolution",
      "tests": [
        "/conf/resolution/local"
      ],
      "text": "A linter MUST replace a reference whose $ref is a fragment with the value the JSON Pointer names in the same document."
    },
    {
      "id": "/req/resolution/external",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "resolution",
      "tests": [
        "/conf/resolution/external"
      ],
      "text": "A linter MUST replace a reference whose $ref names another document with the value its fragment names in that document, after resolving the $ref against the location of the referencing document."
    },
    {
      "id": "/req/resolution/cycle",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "resolution",
      "tests": [
        "/conf/resolution/cycle"
      ],
      "text": "A linter MUST resolve a document whose references form a cycle without failing, and MUST evaluate rules against it."
    },
    {
      "id": "/req/resolution/unresolvable",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "resolution",
      "tests": [
        "/conf/resolution/unresolvable",
        "/conf/resolution/unresolvable-kept"
      ],
      "text": "When a $ref cannot be resolved, a linter MUST produce a result with the code invalid-ref and the severity error, and MUST leave the reference object in place for the rules."
    },
    {
      "id": "/req/linter/reject-invalid",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "loading",
      "tests": [
        "/conf/linter/accept-valid",
        "/conf/extends/base-invalid",
        "/conf/linter/reject-invalid"
      ],
      "text": "A linter MUST reject a ruleset that violates any requirement whose conformance target is ruleset, or that extends, directly or through another ruleset's extends, a ruleset that violates one, and MUST NOT produce results from it."
    },
    {
      "id": "/req/linter/accept-valid",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "loading",
      "tests": [
        "/conf/linter/accept-valid"
      ],
      "text": "A linter MUST load a ruleset that satisfies every requirement whose conformance target is ruleset, when every ruleset it extends and every custom function it names can be loaded, unless /req/overrides/checked-when-applied has it rejected for the document being linted."
    },
    {
      "id": "/req/extends/load",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "loading",
      "tests": [
        "/conf/extends/load",
        "/conf/linter/walkthrough"
      ],
      "text": "A linter MUST load every ruleset identified in extends and make each of its rules available to the extending ruleset under its rule name."
    },
    {
      "id": "/req/extends/unresolvable",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "loading",
      "tests": [
        "/conf/extends/resolvable",
        "/conf/extends/unresolvable"
      ],
      "text": "A linter MUST reject a ruleset whose extends identifies a ruleset it cannot load."
    },
    {
      "id": "/req/extension-properties/ignored",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "loading",
      "tests": [
        "/conf/extension-properties/ignored"
      ],
      "text": "A linter MUST NOT let an extension property change which results it produces."
    },
    {
      "id": "/req/overrides/scope",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/linter/walkthrough",
        "/conf/overrides/scope-match",
        "/conf/overrides/scope-no-match",
        "/conf/overrides/scope-outside-ruleset-directory",
        "/conf/overrides/scope-ruleset-directory"
      ],
      "text": "A linter MUST apply an override to a document only when the document's path, relative to the directory of the ruleset file and with / as the separator, matches one of the override's files globs."
    },
    {
      "id": "/req/overrides/order",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/overrides/order"
      ],
      "text": "When several overrides match a document, a linter MUST apply them in array order, each on top of the previous, and all of them on top of the ruleset itself."
    },
    {
      "id": "/req/overrides/extends",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/overrides/extends",
        "/conf/overrides/extends-with-rules",
        "/conf/overrides/extends-without-rules"
      ],
      "text": "For a document a file-scoped override applies to, a linter MUST load the rulesets the override's extends identifies and make their rules available in addition to those of the rulesets the ruleset extends, or, when the override has no rules, in place of them."
    },
    {
      "id": "/req/overrides/aliases",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/overrides/aliases-existing-rule",
        "/conf/overrides/aliases-new-rule",
        "/conf/overrides/aliases-outside-globs"
      ],
      "text": "For a document a file-scoped override applies to, a linter MUST resolve the alias references of each rule the override defines and the ruleset does not against the override's aliases and the ruleset's, the override's alias taking precedence for a name both declare, and MUST resolve the alias references of every other rule as if the override declared no aliases."
    },
    {
      "id": "/req/overrides/reject-foreign-property",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/overrides/unknown-property-not-applied",
        "/conf/overrides/unknown-property-applied"
      ],
      "text": "For a document a file-scoped override applies to, a linter MUST reject the ruleset when the override has a property the Ruleset Object does not have."
    },
    {
      "id": "/req/overrides/reject-unknown-shorthand",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/shorthands/override-own-rule",
        "/conf/shorthands/override-unknown-not-applied",
        "/conf/shorthands/override-unknown"
      ],
      "text": "For a document a file-scoped override applies to, a linter MUST reject the ruleset when a shorthand in the override's rules names a rule the ruleset neither defines nor inherits."
    },
    {
      "id": "/req/overrides/reject-undeclared-alias",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/overrides/redefined-rule-alias-declared",
        "/conf/overrides/redefined-rule-alias-applied"
      ],
      "text": "For a document a file-scoped override applies to, a linter MUST reject the ruleset when a rule the override redefines has an alias reference to an alias that the ruleset defining the rule does not declare."
    },
    {
      "id": "/req/overrides/checked-when-applied",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/overrides/unknown-property-not-applied",
        "/conf/shorthands/override-unknown-not-applied"
      ],
      "text": "A linter MUST NOT reject a ruleset for the reasons in the three requirements above when the override applies to no document being linted."
    },
    {
      "id": "/req/overrides/pointer-scope",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-overrides",
      "tests": [
        "/conf/overrides/pointer-scope",
        "/conf/overrides/pointer-scope-at"
      ],
      "text": "For a pointer-scoped override, a linter MUST apply the severities only to results whose path is at or below the location the pointer names."
    },
    {
      "id": "/req/severity/numeric-equivalence",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/severity/numeric-equivalence"
      ],
      "text": "A linter MUST treat each numeric severity as equivalent to the name it is paired with in the table in #rule-severity."
    },
    {
      "id": "/req/severity/default",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/extends/redefine-keeps-properties",
        "/conf/severity/default"
      ],
      "text": "When neither a rule nor any definition it redefines has a severity, a linter MUST use warn."
    },
    {
      "id": "/req/rules/recommended",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/rules/recommended-default",
        "/conf/rules/recommended-false"
      ],
      "text": "A linter MUST enable every rule a ruleset defines in its own rules whose recommended is true or absent, and MUST NOT enable one whose recommended is false unless a shorthand in an extending ruleset enables it."
    },
    {
      "id": "/req/extends/mode-recommended",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/extends/mode-default",
        "/conf/extends/mode-recommended"
      ],
      "text": "When a ruleset is extended with the mode recommended, or without a mode, a linter MUST enable exactly those rules inherited from it whose recommended is true or absent."
    },
    {
      "id": "/req/extends/mode-all",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/extends/mode-all",
        "/conf/extends/mode-all-extra-element"
      ],
      "text": "When a ruleset is extended with the mode all, a linter MUST enable every rule inherited from it."
    },
    {
      "id": "/req/extends/mode-off",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/extends/mode-off"
      ],
      "text": "When a ruleset is extended with the mode off, a linter MUST make every rule inherited from it available and MUST NOT enable any of them."
    },
    {
      "id": "/req/extends/order",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/extends/precedence",
        "/conf/extends/precedence-order"
      ],
      "text": "A linter MUST apply definitions and adjustments of a rule in this order: the rulesets identified by extends, in array order, then the extending ruleset's own rules."
    },
    {
      "id": "/req/rules/redefinition-merge",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/extends/redefine-keeps-properties"
      ],
      "text": "When a Rule Object redefines a rule defined earlier in that order, a linter MUST replace each property the Rule Object has and MUST keep every property it does not have."
    },
    {
      "id": "/req/shorthands/severity",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/shorthands/severity"
      ],
      "text": "For a shorthand that is a severity name, a linter MUST set the rule's effective severity to it and MUST enable the rule, or not enable it when the name is off."
    },
    {
      "id": "/req/shorthands/false",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/shorthands/false-control",
        "/conf/shorthands/false"
      ],
      "text": "For a shorthand that is false, a linter MUST NOT enable the rule and MUST leave its effective severity unchanged."
    },
    {
      "id": "/req/shorthands/true",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/linter/walkthrough",
        "/conf/shorthands/true-enables",
        "/conf/shorthands/true-keeps-severity",
        "/conf/shorthands/true-off"
      ],
      "text": "For a shorthand that is true, a linter MUST enable the rule unless its effective severity is off, and MUST leave the effective severity unchanged, including a severity set by an earlier ruleset in the chain."
    },
    {
      "id": "/req/severity/off",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "rule-state",
      "tests": [
        "/conf/rules/recommended-false",
        "/conf/severity/off-control",
        "/conf/shorthands/false-control",
        "/conf/severity/off",
        "/conf/shorthands/false"
      ],
      "text": "A linter MUST NOT evaluate a rule that is not enabled, whether its effective severity is off, a shorthand is false, or its recommended is false and nothing enables it, and MUST NOT produce results for it."
    },
    {
      "id": "/req/formats/identifiers",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-selection",
      "tests": [
        "/conf/formats/detect-aas2-6",
        "/conf/formats/detect-aas2-needs-patch",
        "/conf/formats/detect-arazzo",
        "/conf/formats/detect-json-schema-2020-12",
        "/conf/formats/detect-json-schema-loose",
        "/conf/formats/detect-number-version",
        "/conf/formats/detect-oas2",
        "/conf/formats/detect-oas3-1"
      ],
      "text": "A linter MUST detect a format for a document when the document's root is an object and the condition the table in #formats gives for the identifier holds, and MUST NOT detect it otherwise, among the identifiers /req/formats/detection-scope lets it detect."
    },
    {
      "id": "/req/formats/detection-scope",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-selection",
      "tests": [
        "/conf/formats/detection-declared-only"
      ],
      "text": "A linter MUST detect a document's formats only among the identifiers named in the formats of the ruleset, of its rules, and of the rulesets it extends and their rules. An identifier named only by a target of a scoped alias is never detected."
    },
    {
      "id": "/req/formats/rule-scope",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-selection",
      "tests": [
        "/conf/formats/rule-scope"
      ],
      "text": "A linter MUST evaluate a rule that has formats only against documents that have at least one of those formats."
    },
    {
      "id": "/req/formats/ruleset-default",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-selection",
      "tests": [
        "/conf/formats/ruleset-default",
        "/conf/formats/unrecognized-unscoped",
        "/conf/linter/walkthrough"
      ],
      "text": "A linter MUST treat a rule without formats, defined in a ruleset with formats, as having the formats of the ruleset that defines it, also when another ruleset extends it."
    },
    {
      "id": "/req/formats/rule-overrides-ruleset",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-selection",
      "tests": [
        "/conf/formats/rule-overrides-ruleset"
      ],
      "text": "When both a rule and its ruleset have formats, a linter MUST use the rule's and ignore the ruleset's for that rule."
    },
    {
      "id": "/req/formats/unscoped-runs-everywhere",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-selection",
      "tests": [
        "/conf/formats/unscoped"
      ],
      "text": "A linter MUST evaluate a rule that has no formats, in a ruleset that has none, against every document, whatever its formats."
    },
    {
      "id": "/req/formats/unrecognized-document",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "document-selection",
      "tests": [
        "/conf/formats/unrecognized-document",
        "/conf/formats/unrecognized-unscoped"
      ],
      "text": "When a ruleset has formats, directly or through its rules, and a document has none of them, a linter MUST produce one result with the code unrecognized-format and the severity warn, and MUST still run every rule that has no formats of its own and inherits none from the ruleset."
    },
    {
      "id": "/req/given/evaluate",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/given/evaluate-all-matches",
        "/conf/given/evaluate-multiple-expressions"
      ],
      "text": "For every rule that is enabled for a document, a linter MUST evaluate each path expression in given against the document and apply the rule's then to every matched node."
    },
    {
      "id": "/req/given/no-match",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/given/match",
        "/conf/given/no-match"
      ],
      "text": "A linter MUST NOT produce a result for a rule whose given matches no node in the document."
    },
    {
      "id": "/req/given/resolved",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/given/resolved-false",
        "/conf/given/resolved-default"
      ],
      "text": "A linter MUST evaluate given against the resolved document, unless the rule sets resolved to false, in which case it MUST evaluate given against the document as written."
    },
    {
      "id": "/req/given/jsonpath",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/given/jsonpath-filter"
      ],
      "text": "A linter MUST evaluate a JSONPath expression as JSONPath-Plus 10.4.0 JSONPATH-PLUS evaluates it, including its filter expressions in parentheses, such as $..parameters[?(@.in === \"header\")]."
    },
    {
      "id": "/req/given/once-per-node",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/given/once-per-node"
      ],
      "text": "A linter MUST apply a rule's then to a node once, even when several of the rule's path expressions match it."
    },
    {
      "id": "/req/given/alias-expansion",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/given/alias-expansion",
        "/conf/linter/walkthrough"
      ],
      "text": "A linter MUST evaluate an alias reference as the set of the named alias's path expressions, each with the remainder of the reference after the alias name appended to it."
    },
    {
      "id": "/req/aliases/compose",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/aliases/compose"
      ],
      "text": "When an alias's path expressions contain alias references, a linter MUST expand those references in turn, until no reference remains."
    },
    {
      "id": "/req/aliases/scoped",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "node-selection",
      "tests": [
        "/conf/aliases/scoped-last-target",
        "/conf/aliases/scoped-no-target",
        "/conf/aliases/scoped-oas2",
        "/conf/aliases/scoped-oas3"
      ],
      "text": "For a scoped alias, a linter MUST use the given of the last target whose formats include a format of the document, and MUST match no node with it when no target does."
    },
    {
      "id": "/req/then/apply-each",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-functions",
      "tests": [
        "/conf/then/apply-each",
        "/conf/then/apply-each-problem"
      ],
      "text": "For each matched node, a linter MUST apply every function invocation in then, and MUST report each problem a function returns as a result."
    },
    {
      "id": "/req/then/field",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-functions",
      "tests": [
        "/conf/then/field",
        "/conf/then/field-jsonpath",
        "/conf/then/field-missing",
        "/conf/then/field-path"
      ],
      "text": "When an invocation has field, a linter MUST apply the function to each value field selects in the matched node: the property it names, the value at the path of property names and indices it names, or every value its JSONPath expression selects when it starts with $. When field selects nothing, the linter MUST apply the function once, to no value, and a result MUST have the path and range of the matched node. A result for a selected value MUST have the path of that value."
    },
    {
      "id": "/req/then/field-key",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-functions",
      "tests": [
        "/conf/then/field-key"
      ],
      "text": "When field is @key, a linter MUST apply the function once to each property key of the matched node, and a result for a key MUST have the path of that property."
    },
    {
      "id": "/req/then/function-options",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "applying-functions",
      "tests": [
        "/conf/then/function-options"
      ],
      "text": "A linter MUST pass the invocation's functionOptions to the function."
    },
    {
      "id": "/req/result/fields",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [
        "/conf/result/fields"
      ],
      "text": "Every result a linter produces MUST have code, path, severity, message, and range."
    },
    {
      "id": "/req/result/code",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [
        "/conf/result/code"
      ],
      "text": "The code of a result a rule produces MUST be its rule name. The code of a result the linter produces itself MUST be one of those in the table below."
    },
    {
      "id": "/req/result/severity",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [
        "/conf/linter/walkthrough",
        "/conf/result/severity",
        "/conf/severity/result"
      ],
      "text": "The severity of a result MUST be the numeric form of the rule's effective severity."
    },
    {
      "id": "/req/result/range",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [
        "/conf/result/range",
        "/conf/result/range-utf16"
      ],
      "text": "The range of a result MUST locate the value the result is about in the source text of the document: start at its first character and end just after its last, each with a zero-based line and a zero-based character counted in UTF-16 code units."
    },
    {
      "id": "/req/result/source",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [
        "/conf/result/source"
      ],
      "text": "When the document was read from a file path or URL, every result for it MUST carry that location in source, as an absolute path or the URL."
    },
    {
      "id": "/req/result/order",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [
        "/conf/result/order"
      ],
      "text": "A linter MUST list results in the order of the documents they belong to, as the documents were given, and within a document by the line and then the character of range.start, and then by code."
    },
    {
      "id": "/req/result/reference-target",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [
        "/conf/resolution/shared-reference"
      ],
      "text": "When a rule ran against the resolved document and the value a result is about was reached through a reference, the result MUST carry the path, range, and source of the value where it is written, and a value reached through several references MUST produce one result."
    },
    {
      "id": "/rec/result/documentation-url",
      "kind": "recommendation",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "results",
      "tests": [],
      "text": "When the rule that produced a result has a documentationUrl, a linter SHOULD carry it in the result's documentationUrl, and when the rule has none but the ruleset that defines it has one, that URL followed by # and the rule name."
    },
    {
      "id": "/req/message/override",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "message",
      "tests": [
        "/conf/message/override"
      ],
      "text": "When a rule has message, the message of every result it produces MUST be the rule's message with each placeholder substituted."
    },
    {
      "id": "/req/message/placeholders",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "message",
      "tests": [
        "/conf/message/placeholder-description",
        "/conf/message/placeholder-path",
        "/conf/message/placeholder-property"
      ],
      "text": "A linter MUST substitute {{error}} with the message the function produced, {{description}} with the rule's description, {{path}} with the path to the offending value as a JSON Pointer RFC6901 with a leading #, {{property}} with the last key or index of that path, and {{value}} with the offending value."
    },
    {
      "id": "/req/message/default",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "message",
      "tests": [
        "/conf/message/default-description"
      ],
      "text": "When a rule has no message, the message of every result it produces MUST be the rule's description, or the message the function produced when the rule has no description."
    },
    {
      "id": "/req/functions/input-types",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "core-functions",
      "tests": [
        "/conf/functions/input-types"
      ],
      "text": "A core function MUST pass when the value it is applied to is absent or of a type the function does not apply to, unless its requirement below says otherwise."
    },
    {
      "id": "/req/functions/truthy",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-truthy",
      "tests": [
        "/conf/functions/truthy"
      ],
      "text": "truthy MUST fail when the value is absent, false, \"\", 0, or null, and MUST pass otherwise, including for an empty array and an empty object."
    },
    {
      "id": "/req/functions/falsy",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-falsy",
      "tests": [
        "/conf/functions/falsy"
      ],
      "text": "falsy MUST fail when the value is present and not one of false, \"\", 0, or null, and MUST pass otherwise."
    },
    {
      "id": "/req/functions/defined",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-defined",
      "tests": [
        "/conf/functions/defined"
      ],
      "text": "defined MUST fail when the value is absent and MUST pass when it is present, whatever it is."
    },
    {
      "id": "/req/functions/undefined",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-undefined",
      "tests": [
        "/conf/functions/undefined"
      ],
      "text": "undefined MUST fail when the value is present and MUST pass when it is absent."
    },
    {
      "id": "/req/functions/pattern",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-pattern",
      "tests": [
        "/conf/functions/pattern"
      ],
      "text": "pattern MUST fail when the option match is given and the value does not match it, or when the option notMatch is given and the value matches it. Both options are regular expressions as defined by ECMAScript ECMA-262-2025."
    },
    {
      "id": "/req/functions/casing",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-casing",
      "tests": [
        "/conf/functions/casing",
        "/conf/functions/casing-non-ascii",
        "/conf/functions/casing-types"
      ],
      "text": "casing MUST fail when the value is a non-empty string that is not written in the case named by the option type: one of flat, camel, pascal, kebab, cobol, snake, and macro, where only ASCII letters and digits count as written in a case."
    },
    {
      "id": "/req/functions/length",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-length",
      "tests": [
        "/conf/functions/length",
        "/conf/functions/length-code-units",
        "/conf/functions/length-min"
      ],
      "text": "length MUST fail when the length of the value is below the option min or above the option max, where the length of a string is its number of UTF-16 code units, of an array its number of elements, of an object its number of properties, and of a number the number itself."
    },
    {
      "id": "/req/functions/alphabetical",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-alphabetical",
      "tests": [
        "/conf/functions/alphabetical",
        "/conf/functions/alphabetical-case",
        "/conf/functions/alphabetical-keyed-by",
        "/conf/functions/alphabetical-numbers"
      ],
      "text": "alphabetical MUST fail when the elements of an array, or the keys of an object, are not in ascending order, where numbers are compared by value, strings as localeCompare of ECMAScript ECMA-402 compares them with no locale given, and two values of different types count as in order. With the option keyedBy, the elements of an array of objects are compared by that property."
    },
    {
      "id": "/req/functions/enumeration",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-enumeration",
      "tests": [
        "/conf/functions/enumeration",
        "/conf/functions/enumeration-types"
      ],
      "text": "enumeration MUST fail when the value is not one of the elements of the option values, compared by JSON type and value, so that \"1\" is not 1 while 1.0 is."
    },
    {
      "id": "/req/functions/schema",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-schema",
      "tests": [
        "/conf/functions/schema",
        "/conf/functions/schema-absent",
        "/conf/functions/schema-all-errors",
        "/conf/functions/schema-default-draft",
        "/conf/functions/schema-dialect",
        "/conf/functions/schema-first-error",
        "/conf/functions/schema-format",
        "/conf/functions/schema-ref"
      ],
      "text": "schema MUST fail when the value is absent, or when it does not validate against the JSON Schema given as the option schema, asserting the format keyword and resolving a $ref within the option against the option itself, with one problem for the first failed keyword, or one per failed keyword when the option allErrors is true. The schema is read in the draft the option dialect names, as the table above defines each draft; with dialect absent or auto, in the draft its $schema names, and in draft 7 when it names none."
    },
    {
      "id": "/req/functions/xor",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-xor",
      "tests": [
        "/conf/functions/xor",
        "/conf/functions/xor-null"
      ],
      "text": "xor MUST fail unless exactly one of the properties named by the option properties is present on the value, where a property is present when the object has the key, whatever its value."
    },
    {
      "id": "/req/functions/or",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-or",
      "tests": [
        "/conf/functions/or",
        "/conf/functions/or-null"
      ],
      "text": "or MUST fail unless at least one of the properties named by the option properties is present on the value, where a property is present when the object has the key, whatever its value."
    },
    {
      "id": "/req/functions/unreferenced-reusable-object",
      "kind": "requirement",
      "class": "linter-core",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "fn-unreferencedreusableobject",
      "tests": [
        "/conf/functions/unreferenced-reusable-object"
      ],
      "text": "unreferencedReusableObject, applied to an object of reusable definitions, MUST fail once for each member that no $ref in the documents being linted points to, where the option reusableObjectsLocation is the JSON Pointer RFC6901 of that object in the document."
    },
    {
      "id": "/req/custom-functions/missing",
      "kind": "requirement",
      "class": "linter-custom-functions",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "custom-functions-contract",
      "tests": [
        "/conf/custom-functions/present",
        "/conf/custom-functions/missing"
      ],
      "text": "A linter MUST reject a ruleset that names a function it cannot load."
    },
    {
      "id": "/req/custom-functions/invoke",
      "kind": "requirement",
      "class": "linter-custom-functions",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "custom-functions-contract",
      "tests": [
        "/conf/custom-functions/invoke"
      ],
      "text": "A linter MUST call a custom function with the value the invocation targets and the invocation's functionOptions, and MUST report each problem the function returns as a result whose message is the problem's message."
    },
    {
      "id": "/req/custom-functions/problem-path",
      "kind": "requirement",
      "class": "linter-custom-functions",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "custom-functions-contract",
      "tests": [
        "/conf/custom-functions/problem-path"
      ],
      "text": "A linter MUST report a problem that carries a path at that path in the document, a problem without one at the matched node, and a problem whose path is not in the document at the document's root."
    },
    {
      "id": "/req/custom-functions/no-problems",
      "kind": "requirement",
      "class": "linter-custom-functions",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "custom-functions-contract",
      "tests": [
        "/conf/custom-functions/returns-nothing"
      ],
      "text": "A linter MUST treat a custom function that returns nothing as returning no problems."
    },
    {
      "id": "/req/custom-functions/javascript-load",
      "kind": "requirement",
      "class": "linter-custom-functions-javascript",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "custom-functions-javascript",
      "tests": [
        "/conf/custom-functions/load-custom-dir",
        "/conf/custom-functions/load-default-dir"
      ],
      "text": "A linter MUST load each name in functions from /.js, resolved relative to the ruleset file, with functions as the directory when functionsDir is absent."
    },
    {
      "id": "/req/custom-functions/javascript-promise",
      "kind": "requirement",
      "class": "linter-custom-functions-javascript",
      "target": "linter",
      "status": "current",
      "since": "draft",
      "section": "custom-functions-javascript",
      "tests": [
        "/conf/custom-functions/javascript-promise"
      ],
      "text": "When a JavaScript custom function returns a promise, a linter MUST wait for it and use the problems it resolves to."
    }
  ],
  "tests": [
    {
      "id": "/conf/aliases/chain",
      "for": [
        "/req/aliases/no-cycle"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An alias defined through another alias, without a cycle, is valid.",
      "dir": "conformance/aliases/chain",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/aliases/compose",
      "for": [
        "/req/aliases/compose"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An alias defined through another alias expands to the full path.",
      "dir": "conformance/aliases/compose",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "info-description",
            "path": [
              "info",
              "description"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/aliases/cycle",
      "for": [
        "/req/aliases/no-cycle"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "Two aliases that refer to each other are invalid.",
      "dir": "conformance/aliases/cycle",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/aliases/name",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An alias name starting with a digit is invalid.",
      "dir": "conformance/aliases/name",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/aliases/name-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An alias name of letters, digits, underscores, and hyphens starting with a letter is valid.",
      "dir": "conformance/aliases/name-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/aliases/scoped-form-missing-formats",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A scoped alias target without `formats` is invalid.",
      "dir": "conformance/aliases/scoped-form-missing-formats",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/aliases/scoped-form-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A scoped alias whose every target has `formats` and `given` is valid.",
      "dir": "conformance/aliases/scoped-form-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/aliases/scoped-last-target",
      "for": [
        "/req/aliases/scoped"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "For an OpenAPI 3.1 document, which has both `oas3` and `oas3_1`, only the last matching target is used.",
      "dir": "conformance/aliases/scoped-last-target",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "info"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/aliases/scoped-no-target",
      "for": [
        "/req/aliases/scoped"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A scoped alias with no target for the document's formats matches nothing; only the format warning is reported.",
      "dir": "conformance/aliases/scoped-no-target",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "unrecognized-format"
          }
        ]
      }
    },
    {
      "id": "/conf/aliases/scoped-oas2",
      "for": [
        "/req/aliases/scoped"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "On an OpenAPI 2 document, the scoped alias uses the `oas2` target.",
      "dir": "conformance/aliases/scoped-oas2",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "parameter-name",
            "path": [
              "parameters",
              "limit",
              "name"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/aliases/scoped-oas3",
      "for": [
        "/req/aliases/scoped"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "On an OpenAPI 3 document, the scoped alias uses the `oas3` target.",
      "dir": "conformance/aliases/scoped-oas3",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "parameter-name",
            "path": [
              "components",
              "parameters",
              "limit",
              "name"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/aliases/simple-form-string",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A simple alias given as a bare string is invalid.",
      "dir": "conformance/aliases/simple-form-string",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/aliases/simple-form-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A simple alias that is an array of path expressions is valid.",
      "dir": "conformance/aliases/simple-form-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/custom-functions/declaration-not-array",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A `functions` value that is a string is invalid.",
      "dir": "conformance/custom-functions/declaration-not-array",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "functions/isEmptyTitle.js"
      ],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/custom-functions/declaration-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`functions` as an array of strings with a `functionsDir` string is valid.",
      "dir": "conformance/custom-functions/declaration-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "checks/isEmptyTitle.js"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/custom-functions/invoke",
      "for": [
        "/req/custom-functions/invoke"
      ],
      "class": "linter-custom-functions",
      "target": "linter",
      "purpose": "The function receives the value and the options, and each problem it returns becomes a result with its message.",
      "dir": "conformance/custom-functions/invoke",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "functions/forbiddenWords.js"
      ],
      "expect": {
        "results": [
          {
            "code": "no-forbidden-words",
            "message": "Contains \"evil\"."
          },
          {
            "code": "no-forbidden-words",
            "message": "Contains \"bad\"."
          }
        ]
      }
    },
    {
      "id": "/conf/custom-functions/javascript-promise",
      "for": [
        "/req/custom-functions/javascript-promise"
      ],
      "class": "linter-custom-functions-javascript",
      "target": "linter",
      "purpose": "A function that returns a promise is awaited, and the problems it resolves to are reported.",
      "dir": "conformance/custom-functions/javascript-promise",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "functions/later.js"
      ],
      "expect": {
        "results": [
          {
            "code": "r",
            "message": "from a promise"
          }
        ]
      }
    },
    {
      "id": "/conf/custom-functions/load-custom-dir",
      "for": [
        "/req/custom-functions/javascript-load"
      ],
      "class": "linter-custom-functions-javascript",
      "target": "linter",
      "purpose": "With `functionsDir`, the function is loaded from that directory.",
      "dir": "conformance/custom-functions/load-custom-dir",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "checks/isEmptyTitle.js"
      ],
      "expect": {
        "results": [
          {
            "code": "title-filled",
            "message": "Title is empty."
          }
        ]
      }
    },
    {
      "id": "/conf/custom-functions/load-default-dir",
      "for": [
        "/req/custom-functions/javascript-load"
      ],
      "class": "linter-custom-functions-javascript",
      "target": "linter",
      "purpose": "A function named in `functions` is loaded from `functions/<name>.js` next to the ruleset.",
      "dir": "conformance/custom-functions/load-default-dir",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "functions/isEmptyTitle.js"
      ],
      "expect": {
        "results": [
          {
            "code": "title-filled",
            "message": "Title is empty."
          }
        ]
      }
    },
    {
      "id": "/conf/custom-functions/missing",
      "for": [
        "/req/custom-functions/missing"
      ],
      "class": "linter-custom-functions",
      "target": "linter",
      "purpose": "A ruleset naming a function whose file does not exist is rejected.",
      "dir": "conformance/custom-functions/missing",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "rejected": true
      }
    },
    {
      "id": "/conf/custom-functions/present",
      "for": [
        "/req/custom-functions/missing"
      ],
      "class": "linter-custom-functions",
      "target": "linter",
      "purpose": "A ruleset naming a function whose file exists is loaded and the function runs.",
      "dir": "conformance/custom-functions/present",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "functions/isEmptyTitle.js"
      ],
      "expect": {
        "results": [
          {
            "code": "title-filled"
          }
        ]
      }
    },
    {
      "id": "/conf/custom-functions/problem-path",
      "for": [
        "/req/custom-functions/problem-path"
      ],
      "class": "linter-custom-functions",
      "target": "linter",
      "purpose": "A problem with a `path` is reported there; one whose path is not in the document is reported at the root.",
      "dir": "conformance/custom-functions/problem-path",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "functions/pathed.js",
        "functions/elsewhere.js"
      ],
      "expect": {
        "results": [
          {
            "code": "pathed",
            "path": [
              "info",
              "title"
            ]
          },
          {
            "code": "elsewhere",
            "path": []
          }
        ]
      }
    },
    {
      "id": "/conf/custom-functions/returns-nothing",
      "for": [
        "/req/custom-functions/no-problems"
      ],
      "class": "linter-custom-functions",
      "target": "linter",
      "purpose": "A function that returns nothing reports no problems, while one that returns a problem does.",
      "dir": "conformance/custom-functions/returns-nothing",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "functions/nothing.js",
        "functions/one.js"
      ],
      "expect": {
        "results": [
          {
            "code": "loud",
            "path": [
              "info"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/document/empty-file",
      "for": [
        "/req/document/any-root"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An empty file is the document `null`, and a rule on `$` sees it.",
      "dir": "conformance/document/empty-file",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": []
          }
        ]
      }
    },
    {
      "id": "/conf/document/root-array",
      "for": [
        "/req/document/any-root"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document whose root is an array is linted, and `$` selects the array.",
      "dir": "conformance/document/root-array",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": []
          }
        ]
      }
    },
    {
      "id": "/conf/document/utf8-keys",
      "for": [
        "/req/document/encoding"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document is read as UTF-8, so non-ASCII keys arrive intact in `path`.",
      "dir": "conformance/document/utf8-keys",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "\u00e9"
            ]
          },
          {
            "code": "s",
            "path": [
              "\ud83d\ude00"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/extends/base-invalid",
      "for": [
        "/req/linter/reject-invalid"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A ruleset that extends a ruleset with an invalid `given` is rejected.",
      "dir": "conformance/extends/base-invalid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "rejected": true
      }
    },
    {
      "id": "/conf/extends/entry-forms-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A string entry and tuples with each of the three modes are valid.",
      "dir": "conformance/extends/entry-forms-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml",
        "a.yaml",
        "b.yaml",
        "c.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/extends/entry-invalid-mode",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An extends tuple with the mode `strict` is invalid.",
      "dir": "conformance/extends/entry-invalid-mode",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/extends/entry-tuple-length",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An extends tuple with a third element is valid; elements after the mode are ignored.",
      "dir": "conformance/extends/entry-tuple-length",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/extends/load",
      "for": [
        "/req/extends/load"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule defined only in the extended ruleset is available to the extending one by name.",
      "dir": "conformance/extends/load",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "base.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary"
          },
          {
            "code": "acme-operation-summary"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/mode-all",
      "for": [
        "/req/extends/mode-all"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With mode `all`, both rules run.",
      "dir": "conformance/extends/mode-all",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r1"
          },
          {
            "code": "r2"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/mode-all-extra-element",
      "for": [
        "/req/extends/mode-all"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `[./base.yaml, all, extra]`, the mode `all` applies and the extra element is ignored.",
      "dir": "conformance/extends/mode-all-extra-element",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "base.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "base-rule"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/mode-default",
      "for": [
        "/req/extends/mode-recommended"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Without a mode, only the rule that is recommended runs.",
      "dir": "conformance/extends/mode-default",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r2"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/mode-off",
      "for": [
        "/req/extends/mode-off"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With mode `off`, no inherited rule runs until it is enabled by name.",
      "dir": "conformance/extends/mode-off",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r1"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/mode-recommended",
      "for": [
        "/req/extends/mode-recommended"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With mode `recommended`, only the rule that is recommended runs.",
      "dir": "conformance/extends/mode-recommended",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r2"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/precedence",
      "for": [
        "/req/extends/order"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The extending ruleset's definition of `r` wins over both extended rulesets.",
      "dir": "conformance/extends/precedence",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml",
        "b.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r",
            "message": "from C"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/precedence-order",
      "for": [
        "/req/extends/order"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Of two extended rulesets defining the same rule, the later one wins.",
      "dir": "conformance/extends/precedence-order",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml",
        "b.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r",
            "message": "from B"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/redefine-keeps-properties",
      "for": [
        "/req/rules/redefinition-merge",
        "/req/severity/default"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A redefinition that sets only `given` and `then` keeps the inherited rule's `severity` and `message`.",
      "dir": "conformance/extends/redefine-keeps-properties",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "base.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 0,
            "message": "base message"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/resolvable",
      "for": [
        "/req/extends/unresolvable"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A ruleset extending a file that exists is loaded and the inherited rule runs.",
      "dir": "conformance/extends/resolvable",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "base.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "base-rule"
          }
        ]
      }
    },
    {
      "id": "/conf/extends/shape-array",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `extends` is an array mixing a string and a tuple is valid.",
      "dir": "conformance/extends/shape-array",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml",
        "other.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/extends/shape-object",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `extends` is an object is invalid.",
      "dir": "conformance/extends/shape-object",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/extends/shape-string",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `extends` is a single string is valid.",
      "dir": "conformance/extends/shape-string",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/extends/unresolvable",
      "for": [
        "/req/extends/unresolvable"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A ruleset extending a file that does not exist is rejected.",
      "dir": "conformance/extends/unresolvable",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "rejected": true
      }
    },
    {
      "id": "/conf/extension-properties/accepted",
      "for": [
        "/per/extension-properties/anywhere"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset with extension properties of several types at the root and on a rule is accepted.",
      "dir": "conformance/extension-properties/accepted",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/extension-properties/ignored",
      "for": [
        "/req/extension-properties/ignored"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Extension properties at the root and on a rule change nothing about the results.",
      "dir": "conformance/extension-properties/ignored",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary"
          },
          {
            "code": "acme-operation-summary"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-aas2-6",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document with `asyncapi: 2.6.0` is `aas2_6` and not `aas2_5`.",
      "dir": "conformance/formats/detect-aas2-6",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-aas2_6"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-aas2-needs-patch",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`asyncapi: \"2.6\"` without a patch number is not `aas2`, while `2.6.0` is.",
      "dir": "conformance/formats/detect-aas2-needs-patch",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-aas2"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-arazzo",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document with `arazzo: 1.0.1` is `arazzo1_0`.",
      "dir": "conformance/formats/detect-arazzo",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-arazzo1_0"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-json-schema-2020-12",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A `$schema` of draft 2020-12 is `jsonSchemaDraft2020_12` and not draft 7.",
      "dir": "conformance/formats/detect-json-schema-2020-12",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-jsonSchemaDraft2020_12"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-json-schema-loose",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document with `type: object` and no `$schema` is `jsonSchemaLoose` but not `jsonSchema`.",
      "dir": "conformance/formats/detect-json-schema-loose",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-jsonSchemaLoose"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-number-version",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An unquoted `openapi: 3.0` is the number 3, whose string form is `3`, so the document is `oas3` but not `oas3_0`.",
      "dir": "conformance/formats/detect-number-version",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-oas3"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-oas2",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document with `swagger: \"2.0\"` is `oas2` and not `oas3`.",
      "dir": "conformance/formats/detect-oas2",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-oas2"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detect-oas3-1",
      "for": [
        "/req/formats/identifiers"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An OpenAPI 3.1 document is detected as `oas3_1` and not as `oas3_0`.",
      "dir": "conformance/formats/detect-oas3-1",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "is-oas3-1"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/detection-declared-only",
      "for": [
        "/req/formats/detection-scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`oas3_1` is not detected when no rule names it, so for an OpenAPI 3.1 document the alias uses its `oas3` target, though an `oas3_1` target comes last.",
      "dir": "conformance/formats/detection-declared-only",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "info"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/formats/rule-overrides-ruleset",
      "for": [
        "/req/formats/rule-overrides-ruleset"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule's own `formats` replaces the ruleset's.",
      "dir": "conformance/formats/rule-overrides-ruleset",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/rule-scope",
      "for": [
        "/req/formats/rule-scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Of two rules scoped to different formats, only the one whose format the document has runs.",
      "dir": "conformance/formats/rule-scope",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "only-oas2"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/ruleset-default",
      "for": [
        "/req/formats/ruleset-default"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule without `formats` takes the ruleset's, so it does not run on a document of another format, while a rule scoped to that format does.",
      "dir": "conformance/formats/ruleset-default",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "s"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/shape-string",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `formats` is a string is invalid.",
      "dir": "conformance/formats/shape-string",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/formats/shape-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`formats` as an array of strings on the ruleset, a rule, an override, and an alias target is valid.",
      "dir": "conformance/formats/shape-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/formats/unknown-identifier",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule whose `formats` names an identifier outside the table, `oas31`, is invalid.",
      "dir": "conformance/formats/unknown-identifier",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/formats/unrecognized-document",
      "for": [
        "/req/formats/unrecognized-document"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document that has none of the ruleset's formats gets one warning and no rule results.",
      "dir": "conformance/formats/unrecognized-document",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "unrecognized-format",
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/formats/unrecognized-unscoped",
      "for": [
        "/req/formats/unrecognized-document",
        "/req/formats/ruleset-default"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document with none of the ruleset's formats gets the warning, the ruleset's own rule does not run, and an unscoped rule from an extended ruleset does.",
      "dir": "conformance/formats/unrecognized-unscoped",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "base.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "unrecognized-format",
            "severity": 1
          },
          {
            "code": "s"
          }
        ]
      }
    },
    {
      "id": "/conf/formats/unscoped",
      "for": [
        "/req/formats/unscoped-runs-everywhere"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Without `formats` anywhere, a rule runs on a document of no known format.",
      "dir": "conformance/formats/unscoped",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/alphabetical",
      "for": [
        "/req/functions/alphabetical"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`alphabetical` fails on an unsorted array and passes on a sorted one.",
      "dir": "conformance/functions/alphabetical",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "sorted"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/alphabetical-case",
      "for": [
        "/req/functions/alphabetical"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Strings are compared with `localeCompare`, so `a` comes before `B` and `B` after `a`.",
      "dir": "conformance/functions/alphabetical-case",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "bad",
              "0"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/alphabetical-keyed-by",
      "for": [
        "/req/functions/alphabetical"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `keyedBy`, an array of objects is compared by that property.",
      "dir": "conformance/functions/alphabetical-keyed-by",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "tags-sorted"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/alphabetical-numbers",
      "for": [
        "/req/functions/alphabetical"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Numbers are compared by value, so `[2, 10]` is in order and `[10, 9]` is not.",
      "dir": "conformance/functions/alphabetical-numbers",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "bad",
              "0"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/casing",
      "for": [
        "/req/functions/casing"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`casing` with `type: kebab` fails on a camel-case string.",
      "dir": "conformance/functions/casing",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "kebab"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/casing-non-ascii",
      "for": [
        "/req/functions/casing"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Only ASCII letters count, so `\u00e9clair` is not camel case; the empty string passes.",
      "dir": "conformance/functions/casing-non-ascii",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "a"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/casing-types",
      "for": [
        "/req/functions/casing"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Each case accepts a value written in it and rejects one written in another case.",
      "dir": "conformance/functions/casing-types",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "camel"
          },
          {
            "code": "pascal"
          },
          {
            "code": "snake"
          },
          {
            "code": "macro"
          },
          {
            "code": "cobol"
          },
          {
            "code": "flat"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/defined",
      "for": [
        "/req/functions/defined"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`defined` fails on an absent property and passes on a present one.",
      "dir": "conformance/functions/defined",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "has-description"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/enumeration",
      "for": [
        "/req/functions/enumeration"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`enumeration` fails on a value outside `values`.",
      "dir": "conformance/functions/enumeration",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "x"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/enumeration-types",
      "for": [
        "/req/functions/enumeration"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`\"1\"` is not one of `[1]`, while `1.0` is.",
      "dir": "conformance/functions/enumeration-types",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "s"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/falsy",
      "for": [
        "/req/functions/falsy"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`falsy` fails on an empty array, an empty object, and a string, and passes on `false`, `\"\"`, `0`, and `null`.",
      "dir": "conformance/functions/falsy",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "e"
            ]
          },
          {
            "path": [
              "f"
            ]
          },
          {
            "path": [
              "g"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/input-types",
      "for": [
        "/req/functions/input-types"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`pattern` passes on a number and on an absent value, and fails only on the string that does not match; `xor` passes on a string.",
      "dir": "conformance/functions/input-types",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "starts-with-a",
            "path": [
              "s"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/length",
      "for": [
        "/req/functions/length"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`length` with `max: 4` fails on a string of six characters and an array of five elements, and passes on a number below the bound.",
      "dir": "conformance/functions/length",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "long"
            ]
          },
          {
            "path": [
              "many"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/length-code-units",
      "for": [
        "/req/functions/length"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A string's length is its number of UTF-16 code units: `\u00e9` is one, an emoji two.",
      "dir": "conformance/functions/length-code-units",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "e"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/length-min",
      "for": [
        "/req/functions/length"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`length` with `min: 2` fails on an object with one property and a string of one character, and passes on an object with two.",
      "dir": "conformance/functions/length-min",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "at-least-two",
            "path": [
              "o"
            ]
          },
          {
            "code": "at-least-two",
            "path": [
              "s"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/or",
      "for": [
        "/req/functions/or"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`or` fails unless at least one of `properties` is present.",
      "dir": "conformance/functions/or",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "neither"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/or-null",
      "for": [
        "/req/functions/or"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A key whose value is null counts as present, so `{a: null}` satisfies `or` and `{}` does not.",
      "dir": "conformance/functions/or-null",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "none"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/pattern",
      "for": [
        "/req/functions/pattern"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`match` fails on a string that does not match, `notMatch` fails on one that does.",
      "dir": "conformance/functions/pattern",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "must-match",
            "path": [
              "b"
            ]
          },
          {
            "code": "must-not-match",
            "path": [
              "a"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`schema` fails on a value that does not validate against the given JSON Schema.",
      "dir": "conformance/functions/schema",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "x"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema-absent",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`schema` fails on an absent value.",
      "dir": "conformance/functions/schema-absent",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "contact-shape"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema-all-errors",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `allErrors: true`, a value that fails two keywords gets two problems.",
      "dir": "conformance/functions/schema-all-errors",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "v"
            ]
          },
          {
            "code": "r",
            "path": [
              "v"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema-default-draft",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Without `$schema` or `dialect`, the schema is read as draft 7: `prefixItems` is ignored, `required` is not.",
      "dir": "conformance/functions/schema-default-draft",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "needs-a"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema-dialect",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `dialect: draft2020-12`, `prefixItems` applies.",
      "dir": "conformance/functions/schema-dialect",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "prefix"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema-first-error",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Without `allErrors`, a value that fails two keywords gets one problem.",
      "dir": "conformance/functions/schema-first-error",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "v"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema-format",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The `format` keyword is asserted, so `not-an-email` fails `format: email`.",
      "dir": "conformance/functions/schema-format",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "bad"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/schema-ref",
      "for": [
        "/req/functions/schema"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A `$ref` inside the option resolves against the option's own `$defs`.",
      "dir": "conformance/functions/schema-ref",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "v"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/truthy",
      "for": [
        "/req/functions/truthy"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`truthy` fails on `false`, `\"\"`, `0`, and `null`, and passes on an empty array, an empty object, and a string.",
      "dir": "conformance/functions/truthy",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "a"
            ]
          },
          {
            "path": [
              "b"
            ]
          },
          {
            "path": [
              "c"
            ]
          },
          {
            "path": [
              "d"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/undefined",
      "for": [
        "/req/functions/undefined"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`undefined` fails on a present property and passes on an absent one.",
      "dir": "conformance/functions/undefined",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "no-title"
          }
        ]
      }
    },
    {
      "id": "/conf/functions/unreferenced-reusable-object",
      "for": [
        "/req/functions/unreferenced-reusable-object"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`unreferencedReusableObject` reports a member of the container that nothing references.",
      "dir": "conformance/functions/unreferenced-reusable-object",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "components",
              "schemas",
              "Unused"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/xor",
      "for": [
        "/req/functions/xor"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`xor` fails unless exactly one of `properties` is present.",
      "dir": "conformance/functions/xor",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "both"
            ]
          },
          {
            "path": [
              "neither"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/functions/xor-null",
      "for": [
        "/req/functions/xor"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A key whose value is null counts as present, so `{a: null, b: 1}` has two of the properties.",
      "dir": "conformance/functions/xor-null",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "two"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/given/alias-declared",
      "for": [
        "/req/given/alias-defined"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule referencing an alias the ruleset declares is valid.",
      "dir": "conformance/given/alias-declared",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/given/alias-expansion",
      "for": [
        "/req/given/alias-expansion"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`#Info.description` is evaluated as `$..info.description`.",
      "dir": "conformance/given/alias-expansion",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "info-description",
            "path": [
              "info",
              "description"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/given/alias-redefined-both",
      "for": [
        "/req/given/alias-defined"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule that redefines an inherited rule with an alias both rulesets declare is valid.",
      "dir": "conformance/given/alias-redefined-both",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/given/alias-redefined-own",
      "for": [
        "/req/given/alias-defined"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule that redefines an inherited rule with an alias only the extending ruleset declares is invalid.",
      "dir": "conformance/given/alias-redefined-own",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/given/alias-undefined",
      "for": [
        "/req/given/alias-defined"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule referencing an alias the ruleset does not declare is invalid.",
      "dir": "conformance/given/alias-undefined",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/given/bare-property-name",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule whose `given` is a bare property name is invalid.",
      "dir": "conformance/given/bare-property-name",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/given/evaluate-all-matches",
      "for": [
        "/req/given/evaluate"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Two operations without `summary` produce one result each.",
      "dir": "conformance/given/evaluate-all-matches",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary",
            "path": [
              "paths",
              "/pets",
              "get"
            ]
          },
          {
            "code": "acme-operation-summary",
            "path": [
              "paths",
              "/pets",
              "post"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/given/evaluate-multiple-expressions",
      "for": [
        "/req/given/evaluate"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Two path expressions in `given` each produce their results.",
      "dir": "conformance/given/evaluate-multiple-expressions",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "info-filled",
            "path": [
              "info",
              "title"
            ]
          },
          {
            "code": "info-filled",
            "path": [
              "info",
              "description"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/given/jsonpath-filter",
      "for": [
        "/req/given/jsonpath"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A filter expression in parentheses, `?(@.in === \"header\")`, selects the header parameter with an empty name; the index in its path is a string.",
      "dir": "conformance/given/jsonpath-filter",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "param-name",
            "path": [
              "parameters",
              "1",
              "name"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/given/match",
      "for": [
        "/req/given/no-match"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The same rule on a document where `given` matches produces results.",
      "dir": "conformance/given/match",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "no-paths"
          }
        ]
      }
    },
    {
      "id": "/conf/given/no-match",
      "for": [
        "/req/given/no-match"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule whose `given` matches nothing produces no results, even though its function would fail on any node.",
      "dir": "conformance/given/no-match",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": []
      }
    },
    {
      "id": "/conf/given/once-per-node",
      "for": [
        "/req/given/once-per-node"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A node matched by three path expressions of one rule is checked once.",
      "dir": "conformance/given/once-per-node",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "info"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/given/path-expression-forms",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A JSONPath expression starting with `$` and an alias reference starting with `#` are both valid.",
      "dir": "conformance/given/path-expression-forms",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/given/present",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `given` and `then` is valid.",
      "dir": "conformance/given/present",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/given/required",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `then` but no `given` is invalid.",
      "dir": "conformance/given/required",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/given/resolved-default",
      "for": [
        "/req/given/resolved"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "By default `given` sees the resolved document, where the `$ref` has been replaced by a schema with `type`.",
      "dir": "conformance/given/resolved-default",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": []
      }
    },
    {
      "id": "/conf/given/resolved-false",
      "for": [
        "/req/given/resolved"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `resolved: false`, `given` sees the `$ref` object, which has no `type`.",
      "dir": "conformance/given/resolved-false",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "id-has-type"
          }
        ]
      }
    },
    {
      "id": "/conf/given/shape-empty-array",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `given: []` is invalid.",
      "dir": "conformance/given/shape-empty-array",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/given/shape-object",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule whose `given` is an object is invalid.",
      "dir": "conformance/given/shape-object",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/given/shape-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`given` as a single path expression and as an array of them are both valid.",
      "dir": "conformance/given/shape-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/linter/accept-valid",
      "for": [
        "/req/linter/reject-invalid",
        "/req/linter/accept-valid"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A valid ruleset is loaded and linting produces its results.",
      "dir": "conformance/linter/accept-valid",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary"
          },
          {
            "code": "acme-operation-summary"
          }
        ]
      }
    },
    {
      "id": "/conf/linter/reject-invalid",
      "for": [
        "/req/linter/reject-invalid"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Given an invalid ruleset, the linter rejects it and produces no results.",
      "dir": "conformance/linter/reject-invalid",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "rejected": true
      }
    },
    {
      "id": "/conf/linter/walkthrough",
      "for": [
        "/req/extends/load",
        "/req/overrides/scope",
        "/req/shorthands/true",
        "/req/formats/ruleset-default",
        "/req/given/alias-expansion",
        "/req/result/severity"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The running example of the Linting chapter: a ruleset that extends a base, enables a rule by shorthand, declares an alias, and overrides a severity for legacy documents, linting one legacy document.",
      "dir": "conformance/linter/walkthrough",
      "ruleset": "ruleset.yaml",
      "document": "legacy/petstore.yaml",
      "files": [
        "acme-base.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "operation-summary",
            "path": [
              "paths",
              "/pets",
              "get"
            ],
            "severity": 0
          },
          {
            "code": "operation-has-tags",
            "path": [
              "paths",
              "/pets",
              "get"
            ],
            "severity": 3
          },
          {
            "code": "operation-id-camel-case",
            "path": [
              "paths",
              "/pets",
              "get",
              "operationId"
            ],
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/message/default-description",
      "for": [
        "/req/message/default"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Without `message`, the result carries the rule's description.",
      "dir": "conformance/message/default-description",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "message": "Every operation needs a summary."
          },
          {
            "message": "Every operation needs a summary."
          }
        ]
      }
    },
    {
      "id": "/conf/message/override",
      "for": [
        "/req/message/override"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule's `message` replaces the reported message.",
      "dir": "conformance/message/override",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "message": "Summary missing here"
          },
          {
            "message": "Summary missing here"
          }
        ]
      }
    },
    {
      "id": "/conf/message/placeholder-description",
      "for": [
        "/req/message/placeholders"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`{{description}}` resolves to the rule's description.",
      "dir": "conformance/message/placeholder-description",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "message": "Every operation needs a summary."
          },
          {
            "message": "Every operation needs a summary."
          }
        ]
      }
    },
    {
      "id": "/conf/message/placeholder-path",
      "for": [
        "/req/message/placeholders"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`{{path}}` is the JSON Pointer to the offending value, with a leading `#`.",
      "dir": "conformance/message/placeholder-path",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "message": "#/info/title"
          }
        ]
      }
    },
    {
      "id": "/conf/message/placeholder-property",
      "for": [
        "/req/message/placeholders"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`{{property}}` resolves to the key of the offending value.",
      "dir": "conformance/message/placeholder-property",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "message": "title"
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/aliases-existing-rule",
      "for": [
        "/req/overrides/aliases"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An alias an override declares does not change a rule the ruleset defines: the rule keeps the ruleset's alias and only its severity changes.",
      "dir": "conformance/overrides/aliases-existing-rule",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "info-description",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/aliases-new-rule",
      "for": [
        "/req/overrides/aliases"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule an override defines resolves aliases against the override's, which take precedence over the ruleset's alias of the same name.",
      "dir": "conformance/overrides/aliases-new-rule",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "override-rule",
            "path": [
              "info",
              "description"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/aliases-outside-globs",
      "for": [
        "/req/overrides/aliases"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Outside the override's globs its aliases have no effect, and the rule keeps its default severity.",
      "dir": "conformance/overrides/aliases-outside-globs",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "info-description",
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/extends",
      "for": [
        "/req/overrides/extends"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An override's `extends` adds rules for the documents it matches.",
      "dir": "conformance/overrides/extends",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "extra.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "extra-rule"
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/extends-with-rules",
      "for": [
        "/req/overrides/extends"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An applying override with `extends` and `rules` adds to the rulesets the ruleset extends: `a`, `b`, and `r` all run.",
      "dir": "conformance/overrides/extends-with-rules",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml",
        "b.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "a"
          },
          {
            "code": "b"
          },
          {
            "code": "r",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/extends-without-rules",
      "for": [
        "/req/overrides/extends"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An applying override with `extends` and no `rules` replaces the rulesets the ruleset extends: `b` and the ruleset's own `r` run, `a` does not.",
      "dir": "conformance/overrides/extends-without-rules",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml",
        "b.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "b"
          },
          {
            "code": "r"
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/file-scoped-empty",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A file-scoped override with neither `extends` nor `rules` is invalid.",
      "dir": "conformance/overrides/file-scoped-empty",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/overrides/file-scoped-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A file-scoped override with `rules`, `extends`, `formats`, `parserOptions`, and `aliases` is valid.",
      "dir": "conformance/overrides/file-scoped-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/overrides/mixed-globs",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An override whose `files` mix a pointer glob and a plain glob is file-scoped, so it can define `rules` with shorthands and is valid.",
      "dir": "conformance/overrides/mixed-globs",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/overrides/order",
      "for": [
        "/req/overrides/order"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Of two overrides that both match, the later one wins.",
      "dir": "conformance/overrides/order",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "severity": 3
          },
          {
            "severity": 3
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/pointer-scope",
      "for": [
        "/req/overrides/pointer-scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A pointer-scoped override silences the rule under its pointer only.",
      "dir": "conformance/overrides/pointer-scope",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "path": [
              "paths",
              "/pets",
              "get"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/pointer-scope-at",
      "for": [
        "/req/overrides/pointer-scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A pointer that names the result's own location silences it.",
      "dir": "conformance/overrides/pointer-scope-at",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "paths",
              "/b",
              "get"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/pointer-scoped-extends",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A pointer-scoped override with `extends` is invalid.",
      "dir": "conformance/overrides/pointer-scoped-extends",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/overrides/pointer-scoped-rule-object",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A pointer-scoped override that defines a rule object is invalid.",
      "dir": "conformance/overrides/pointer-scoped-rule-object",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/overrides/pointer-scoped-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A pointer-scoped override whose `rules` are severities only is valid.",
      "dir": "conformance/overrides/pointer-scoped-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/overrides/redefined-rule-alias-applied",
      "for": [
        "/req/overrides/reject-undeclared-alias"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An override that redefines a rule with an alias only the override declares makes a linter reject the ruleset for a document it applies to.",
      "dir": "conformance/overrides/redefined-rule-alias-applied",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "rejected": true
      }
    },
    {
      "id": "/conf/overrides/redefined-rule-alias-declared",
      "for": [
        "/req/overrides/reject-undeclared-alias"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An override that redefines a rule with an alias the ruleset declares is loaded, and the redefined rule runs.",
      "dir": "conformance/overrides/redefined-rule-alias-declared",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "info"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/scope-match",
      "for": [
        "/req/overrides/scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document inside the override's globs gets the override's severity.",
      "dir": "conformance/overrides/scope-match",
      "ruleset": "ruleset.yaml",
      "document": "legacy/document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "severity": 0
          },
          {
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/scope-no-match",
      "for": [
        "/req/overrides/scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A document outside the override's globs keeps the base severity.",
      "dir": "conformance/overrides/scope-no-match",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "severity": 1
          },
          {
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/scope-outside-ruleset-directory",
      "for": [
        "/req/overrides/scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The same glob does not match a document in a `legacy/` directory that is not next to the ruleset, whatever the working directory.",
      "dir": "conformance/overrides/scope-outside-ruleset-directory",
      "ruleset": "rules/ruleset.yaml",
      "document": "legacy/a.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/scope-ruleset-directory",
      "for": [
        "/req/overrides/scope"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A glob is matched against the document's path relative to the ruleset file's directory, so `legacy/**` matches a document in `legacy/` next to the ruleset.",
      "dir": "conformance/overrides/scope-ruleset-directory",
      "ruleset": "rules/ruleset.yaml",
      "document": "rules/legacy/a.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/overrides/shape-empty",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An empty `overrides` array is invalid.",
      "dir": "conformance/overrides/shape-empty",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/overrides/shape-no-files",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An override without `files` is invalid.",
      "dir": "conformance/overrides/shape-no-files",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/overrides/shape-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An override with a non-empty `files` array is valid.",
      "dir": "conformance/overrides/shape-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/overrides/unknown-property-applied",
      "for": [
        "/req/overrides/reject-foreign-property"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "An override with a property the Ruleset Object does not have makes a linter reject the ruleset for a document it applies to.",
      "dir": "conformance/overrides/unknown-property-applied",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "rejected": true
      }
    },
    {
      "id": "/conf/overrides/unknown-property-not-applied",
      "for": [
        "/req/overrides/reject-foreign-property",
        "/req/overrides/checked-when-applied"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The same override, applying to no document being linted, does not stop the ruleset from loading.",
      "dir": "conformance/overrides/unknown-property-not-applied",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/parser-options/duplicate-keys-default",
      "for": [
        "/req/parser-options/duplicate-keys"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A duplicate key is reported as an error by default.",
      "dir": "conformance/parser-options/duplicate-keys-default",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "parser",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/parser-options/duplicate-keys-off",
      "for": [
        "/req/parser-options/duplicate-keys"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `duplicateKeys: off`, a duplicate key is not reported.",
      "dir": "conformance/parser-options/duplicate-keys-off",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": []
      }
    },
    {
      "id": "/conf/parser-options/duplicate-keys-warn",
      "for": [
        "/req/parser-options/duplicate-keys"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `duplicateKeys: warn`, a duplicate key is reported as a warning.",
      "dir": "conformance/parser-options/duplicate-keys-warn",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "parser",
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/parser-options/incompatible-values",
      "for": [
        "/req/parser-options/incompatible-values"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A YAML mapping key that is a number, not a string, has no JSON representation and is reported as an error by default.",
      "dir": "conformance/parser-options/incompatible-values",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "parser",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/parser-options/shape-extension-property",
      "for": [
        "/req/ruleset/schema",
        "/per/extension-properties/anywhere"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An extension property inside `parserOptions` is invalid: the permission covers the root and rules only, and `parserOptions` admits no other properties.",
      "dir": "conformance/parser-options/shape-extension-property",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/parser-options/shape-unknown-option",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An unknown parser option is invalid.",
      "dir": "conformance/parser-options/shape-unknown-option",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/parser-options/shape-unknown-severity",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`duplicateKeys: critical` is invalid.",
      "dir": "conformance/parser-options/shape-unknown-severity",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/parser-options/shape-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "Both parser options with severity values are valid.",
      "dir": "conformance/parser-options/shape-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/parsing/several-documents",
      "for": [
        "/req/parsing/several-documents"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A YAML file with two documents gets a `parser` error, and the rules run on the first document.",
      "dir": "conformance/parsing/several-documents",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "parser",
            "severity": 0
          },
          {
            "code": "r",
            "path": []
          }
        ]
      }
    },
    {
      "id": "/conf/parsing/syntax-error",
      "for": [
        "/req/parsing/syntax-error"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A YAML document with an unclosed flow sequence is reported as a `parser` error.",
      "dir": "conformance/parsing/syntax-error",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "parser",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/resolution/cycle",
      "for": [
        "/req/resolution/cycle"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A schema that references itself resolves without error, and a rule sees its `type`.",
      "dir": "conformance/resolution/cycle",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "node-is-string"
          }
        ]
      }
    },
    {
      "id": "/conf/resolution/external",
      "for": [
        "/req/resolution/external"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A `$ref` to another file, relative to the document, is replaced by the referenced schema.",
      "dir": "conformance/resolution/external",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "schemas.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "id-is-string"
          }
        ]
      }
    },
    {
      "id": "/conf/resolution/local",
      "for": [
        "/req/resolution/local"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A `$ref` to a pointer in the same document is replaced by the referenced schema, whose `type` the rule then sees.",
      "dir": "conformance/resolution/local",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "id-is-string"
          }
        ]
      }
    },
    {
      "id": "/conf/resolution/shared-reference",
      "for": [
        "/req/result/reference-target"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A schema referenced from two operations fails a rule once, at the place where the schema is written.",
      "dir": "conformance/resolution/shared-reference",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "no-object",
            "path": [
              "components",
              "schemas",
              "Bad",
              "type"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/resolution/unresolvable",
      "for": [
        "/req/resolution/unresolvable"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A `$ref` to a file that does not exist is reported as `invalid-ref` at severity `error`.",
      "dir": "conformance/resolution/unresolvable",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "invalid-ref",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/resolution/unresolvable-kept",
      "for": [
        "/req/resolution/unresolvable"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "After a `$ref` fails to resolve, a rule still sees the reference object.",
      "dir": "conformance/resolution/unresolvable-kept",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "invalid-ref",
            "severity": 0
          },
          {
            "code": "ref-kept",
            "path": [
              "components",
              "schemas",
              "Pet",
              "$ref"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/result/code",
      "for": [
        "/req/result/code"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The `code` of a result is the rule name.",
      "dir": "conformance/result/code",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary"
          },
          {
            "code": "acme-operation-summary"
          }
        ]
      }
    },
    {
      "id": "/conf/result/fields",
      "for": [
        "/req/result/fields"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Every result has the five required fields.",
      "dir": "conformance/result/fields",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "has": [
              "code",
              "path",
              "severity",
              "message",
              "range"
            ]
          },
          {
            "has": [
              "code",
              "path",
              "severity",
              "message",
              "range"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/result/order",
      "for": [
        "/req/result/order"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Results come in order of position, and by code at the same position, whatever the order of the rules.",
      "dir": "conformance/result/order",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "ordered": true,
        "results": [
          {
            "code": "aaa",
            "path": [
              "a"
            ]
          },
          {
            "code": "mmm",
            "path": [
              "a"
            ]
          },
          {
            "code": "zzz",
            "path": [
              "b"
            ]
          },
          {
            "code": "aaa",
            "path": [
              "c"
            ]
          },
          {
            "code": "zzz",
            "path": [
              "d"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/result/range",
      "for": [
        "/req/result/range"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A result about the root value starts at line 0, character 0.",
      "dir": "conformance/result/range",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "root-falsy",
            "range": {
              "start": {
                "line": 0,
                "character": 0
              }
            }
          }
        ]
      }
    },
    {
      "id": "/conf/result/range-utf16",
      "for": [
        "/req/result/range"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A character before the value that needs two UTF-16 code units counts as two, and the end is just after the value.",
      "dir": "conformance/result/range-utf16",
      "ruleset": "ruleset.yaml",
      "document": "document.json",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "b",
            "range": {
              "start": {
                "line": 0,
                "character": 17
              },
              "end": {
                "line": 0,
                "character": 19
              }
            }
          }
        ]
      }
    },
    {
      "id": "/conf/result/severity",
      "for": [
        "/req/result/severity"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule with `severity: hint` reports `severity: 3`.",
      "dir": "conformance/result/severity",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "severity": 3
          },
          {
            "severity": 3
          }
        ]
      }
    },
    {
      "id": "/conf/result/source",
      "for": [
        "/req/result/source"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A result for a document read from a file carries that file's path in `source`.",
      "dir": "conformance/result/source",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary",
            "source": "${document}"
          },
          {
            "code": "acme-operation-summary",
            "source": "${document}"
          }
        ]
      }
    },
    {
      "id": "/conf/rule/all-properties",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule using every property with its documented type is valid.",
      "dir": "conformance/rule/all-properties",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/rule/recommended-not-boolean",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule whose `recommended` is a string is invalid.",
      "dir": "conformance/rule/recommended-not-boolean",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/rule/then-present",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `then` and `given` is valid.",
      "dir": "conformance/rule/then-present",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/rule/then-required",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `given` but no `then` is invalid.",
      "dir": "conformance/rule/then-required",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/rule/type-unknown",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule whose `type` is neither `style` nor `validation` is invalid.",
      "dir": "conformance/rule/type-unknown",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/rule/unknown-property",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with the unknown property `severty` is invalid.",
      "dir": "conformance/rule/unknown-property",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/rules/recommended-default",
      "for": [
        "/req/rules/recommended"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule the ruleset defines runs whether `recommended` is `true` or absent.",
      "dir": "conformance/rules/recommended-default",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r"
          },
          {
            "code": "ctl"
          }
        ]
      }
    },
    {
      "id": "/conf/rules/recommended-false",
      "for": [
        "/req/rules/recommended",
        "/req/severity/off"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule the ruleset defines with `recommended: false` does not run, while its other rules do.",
      "dir": "conformance/rules/recommended-false",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "ctl"
          }
        ]
      }
    },
    {
      "id": "/conf/ruleset/all-properties",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset using every root property with its documented type is valid.",
      "dir": "conformance/ruleset/all-properties",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml",
        "checks/isEmptyTitle.js"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/ruleset/contributes-empty",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset with only `description` is invalid.",
      "dir": "conformance/ruleset/contributes-empty",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/contributes-extends-only",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset with only `extends` is valid.",
      "dir": "conformance/ruleset/contributes-extends-only",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "base.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/ruleset/description-not-string",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `description` is a number is invalid.",
      "dir": "conformance/ruleset/description-not-string",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/document-json",
      "for": [
        "/req/ruleset/document"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A JSON text whose root is an object is valid.",
      "dir": "conformance/ruleset/document-json",
      "ruleset": "ruleset.json",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/ruleset/document-object",
      "for": [
        "/req/ruleset/document"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A YAML document whose root is an object is valid.",
      "dir": "conformance/ruleset/document-object",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/ruleset/document-root-array",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose root value is an array is invalid.",
      "dir": "conformance/ruleset/document-root-array",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/document-single-yaml-document",
      "for": [
        "/req/ruleset/single-document"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A YAML stream with one document, with an explicit document marker, is valid.",
      "dir": "conformance/ruleset/document-single-yaml-document",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/ruleset/document-syntax-error",
      "for": [
        "/req/ruleset/document"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset that is neither JSON nor YAML, here an unclosed flow sequence, is invalid.",
      "dir": "conformance/ruleset/document-syntax-error",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/document-two-yaml-documents",
      "for": [
        "/req/ruleset/single-document"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A YAML stream with two documents is invalid.",
      "dir": "conformance/ruleset/document-two-yaml-documents",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/documentation-url-intranet",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `documentationUrl` names a single-label intranet host, `http://wiki/docs`, is invalid.",
      "dir": "conformance/ruleset/documentation-url-intranet",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/documentation-url-invalid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `documentationUrl` is not a URI is invalid.",
      "dir": "conformance/ruleset/documentation-url-invalid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/documentation-url-mailto",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `documentationUrl` is a `mailto:` URI is invalid: only http, https, and ftp URLs are accepted.",
      "dir": "conformance/ruleset/documentation-url-mailto",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/extension-root-property",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset with the extension property `x-owner` at the root is valid.",
      "dir": "conformance/ruleset/extension-root-property",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/ruleset/rules-not-object",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset whose `rules` is an array is invalid.",
      "dir": "conformance/ruleset/rules-not-object",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/ruleset/unknown-root-property",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A ruleset with `rules` and the unknown root property `rule` is invalid.",
      "dir": "conformance/ruleset/unknown-root-property",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/severity/default",
      "for": [
        "/req/severity/default"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule without `severity` reports with the severity of `warn`.",
      "dir": "conformance/severity/default",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary",
            "severity": 1
          },
          {
            "code": "acme-operation-summary",
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/severity/numeric-equivalence",
      "for": [
        "/req/severity/numeric-equivalence"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule with `severity: 0` reports with the severity of `error`.",
      "dir": "conformance/severity/numeric-equivalence",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary",
            "severity": 0
          },
          {
            "code": "acme-operation-summary",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/severity/off",
      "for": [
        "/req/severity/off"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule with `severity: off` produces no results although it would fail.",
      "dir": "conformance/severity/off",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": []
      }
    },
    {
      "id": "/conf/severity/off-control",
      "for": [
        "/req/severity/off"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The same rule at `warn` produces the results that `off` suppresses.",
      "dir": "conformance/severity/off-control",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary"
          },
          {
            "code": "acme-operation-summary"
          }
        ]
      }
    },
    {
      "id": "/conf/severity/result",
      "for": [
        "/req/result/severity"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule inherited at `warn` and raised to `error` reports with the severity of `error`.",
      "dir": "conformance/severity/result",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "base.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "acme-operation-summary",
            "severity": 0
          },
          {
            "code": "acme-operation-summary",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/severity/values-invalid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `severity: critical` is invalid.",
      "dir": "conformance/severity/values-invalid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/severity/values-name",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `severity: hint` is valid.",
      "dir": "conformance/severity/values-name",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/severity/values-number",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `severity: 3` is valid.",
      "dir": "conformance/severity/values-number",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/shorthands/false",
      "for": [
        "/req/shorthands/false",
        "/req/severity/off"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`false` disables an enabled rule.",
      "dir": "conformance/shorthands/false",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": []
      }
    },
    {
      "id": "/conf/shorthands/false-control",
      "for": [
        "/req/shorthands/false",
        "/req/severity/off"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Without the `false` shorthand, the inherited rule runs.",
      "dir": "conformance/shorthands/false-control",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r"
          }
        ]
      }
    },
    {
      "id": "/conf/shorthands/inherited",
      "for": [
        "/req/shorthands/inherited-only"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A shorthand for a rule inherited through `extends` is valid.",
      "dir": "conformance/shorthands/inherited",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "a.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/shorthands/not-inherited",
      "for": [
        "/req/shorthands/inherited-only"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A shorthand for a rule the ruleset does not inherit is invalid.",
      "dir": "conformance/shorthands/not-inherited",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/shorthands/numeric",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A numeric severity in the shorthand position is invalid.",
      "dir": "conformance/shorthands/numeric",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "a.yaml"
      ],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/shorthands/override-own-rule",
      "for": [
        "/req/overrides/reject-unknown-shorthand"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A shorthand in an applying override for a rule the ruleset defines itself sets its severity.",
      "dir": "conformance/shorthands/override-own-rule",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/shorthands/override-unknown",
      "for": [
        "/req/overrides/reject-unknown-shorthand"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A shorthand in an override for a rule the ruleset neither defines nor inherits makes a linter reject the ruleset for a document the override applies to.",
      "dir": "conformance/shorthands/override-unknown",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "rejected": true
      }
    },
    {
      "id": "/conf/shorthands/override-unknown-not-applied",
      "for": [
        "/req/overrides/reject-unknown-shorthand",
        "/req/overrides/checked-when-applied"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A shorthand for an unknown rule in an override that applies to no document being linted does not stop the ruleset from loading.",
      "dir": "conformance/shorthands/override-unknown-not-applied",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 1
          }
        ]
      }
    },
    {
      "id": "/conf/shorthands/severity",
      "for": [
        "/req/shorthands/severity"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A severity name enables the rule and sets its severity.",
      "dir": "conformance/shorthands/severity",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/shorthands/true-enables",
      "for": [
        "/req/shorthands/true"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`true` enables a rule that is off by default, at the severity it was defined with.",
      "dir": "conformance/shorthands/true-enables",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/shorthands/true-keeps-severity",
      "for": [
        "/req/shorthands/true"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A rule disabled with `false` in one ruleset and re-enabled with `true` in the next keeps the severity it was defined with.",
      "dir": "conformance/shorthands/true-keeps-severity",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml",
        "b.yaml"
      ],
      "expect": {
        "results": [
          {
            "code": "r",
            "severity": 0
          }
        ]
      }
    },
    {
      "id": "/conf/shorthands/true-off",
      "for": [
        "/req/shorthands/true"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "`true` on a rule whose severity is `off` does not enable it.",
      "dir": "conformance/shorthands/true-off",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [
        "a.yaml"
      ],
      "expect": {
        "results": []
      }
    },
    {
      "id": "/conf/shorthands/unknown-name",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An unknown name in the shorthand position is invalid.",
      "dir": "conformance/shorthands/unknown-name",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "a.yaml"
      ],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/shorthands/values-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "Every severity name and both booleans are valid in the shorthand position.",
      "dir": "conformance/shorthands/values-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [
        "a.yaml"
      ],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/then/apply-each",
      "for": [
        "/req/then/apply-each"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "Two invocations that both fail on the same node produce two results.",
      "dir": "conformance/then/apply-each",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "title-checks"
          },
          {
            "code": "title-checks"
          }
        ]
      }
    },
    {
      "id": "/conf/then/apply-each-problem",
      "for": [
        "/req/then/apply-each"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "One invocation whose function returns two problems produces two results.",
      "dir": "conformance/then/apply-each-problem",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r"
          },
          {
            "code": "r"
          }
        ]
      }
    },
    {
      "id": "/conf/then/field",
      "for": [
        "/req/then/field"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `field`, the function sees the named property of the matched node.",
      "dir": "conformance/then/field",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "info-title",
            "path": [
              "info",
              "title"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/then/field-jsonpath",
      "for": [
        "/req/then/field"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A `field` that is a JSONPath expression applies the function to every value it selects.",
      "dir": "conformance/then/field-jsonpath",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r"
          },
          {
            "code": "r"
          }
        ]
      }
    },
    {
      "id": "/conf/then/field-key",
      "for": [
        "/req/then/field-key"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `field: \"@key\"` on a matched object, the function sees each of its property keys; the key that does not match the pattern is reported.",
      "dir": "conformance/then/field-key",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "path-kebab",
            "path": [
              "paths",
              "/Pets_old"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/then/field-missing",
      "for": [
        "/req/then/field"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "With `field` naming a property the node lacks, the function sees no value, so `defined` fails.",
      "dir": "conformance/then/field-missing",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "info-description",
            "path": [
              "info"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/then/field-path",
      "for": [
        "/req/then/field"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "A `field` that is a path of property names reaches a nested value.",
      "dir": "conformance/then/field-path",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "r",
            "path": [
              "info",
              "contact",
              "email"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/then/function-core",
      "for": [
        "/req/then/function-known"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule naming a core function is valid.",
      "dir": "conformance/then/function-core",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/then/function-missing",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An invocation without `function` is invalid.",
      "dir": "conformance/then/function-missing",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/then/function-options",
      "for": [
        "/req/then/function-options"
      ],
      "class": "linter-core",
      "target": "linter",
      "purpose": "The `max` option reaches the `length` function.",
      "dir": "conformance/then/function-options",
      "ruleset": "ruleset.yaml",
      "document": "document.yaml",
      "files": [],
      "expect": {
        "results": [
          {
            "code": "short-title",
            "path": [
              "info",
              "title"
            ]
          }
        ]
      }
    },
    {
      "id": "/conf/then/function-unknown",
      "for": [
        "/req/then/function-known"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule naming a function that is neither core nor declared is invalid.",
      "dir": "conformance/then/function-unknown",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/then/invocation-form-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An invocation with `function`, `field`, and `functionOptions` of the right types is valid.",
      "dir": "conformance/then/invocation-form-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/then/options-not-object",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "An invocation whose `functionOptions` is a string is invalid.",
      "dir": "conformance/then/options-not-object",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/then/options-on-no-option-function",
      "for": [
        "/req/then/function-options-valid"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`truthy` with options is invalid, because it takes none.",
      "dir": "conformance/then/options-on-no-option-function",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/then/options-required-missing",
      "for": [
        "/req/then/function-options-valid"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`length` with empty options is invalid, because it needs `min` or `max`.",
      "dir": "conformance/then/options-required-missing",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/then/options-unknown-value",
      "for": [
        "/req/then/function-options-valid"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`casing` with `type: lower`, which is not a case the function knows, is invalid.",
      "dir": "conformance/then/options-unknown-value",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/then/options-valid",
      "for": [
        "/req/then/function-options-valid"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "Core functions with options that match their tables are valid.",
      "dir": "conformance/then/options-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/then/shape-empty-array",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule with `then: []` is valid.",
      "dir": "conformance/then/shape-empty-array",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    },
    {
      "id": "/conf/then/shape-string",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "A rule whose `then` is a string is invalid.",
      "dir": "conformance/then/shape-string",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "invalid"
      }
    },
    {
      "id": "/conf/then/shape-valid",
      "for": [
        "/req/ruleset/schema"
      ],
      "class": "ruleset-core",
      "target": "ruleset",
      "purpose": "`then` as a single invocation and as an array of them are both valid.",
      "dir": "conformance/then/shape-valid",
      "ruleset": "ruleset.yaml",
      "document": null,
      "files": [],
      "expect": {
        "ruleset": "valid"
      }
    }
  ]
}
