Load local .js, .cjs, and .mjs rulesets with -r. Put functions directly in then.

// rules.mjs
export default {
  rules: {
    'title-required': {
      given: '$.info',
      severity: 'error',
      then: {
        field: 'title',
        function: (value, options, context) => {
          if (!value) {
            return [{ message: 'Set a title.', path: context.path }];
          }
        }
      }
    }
  }
};
vacuum lint api.yaml -r rules.mjs

CommonJS uses module.exports = { rules: { ... } }. Static JavaScript and JSON imports are bundled in Go. No Node process or package install.

Functions

Functions receive (value, options, context) and return undefined or findings, directly or through a Promise. Each finding needs a message. Optional path contains property names and numeric array indices; it defaults to context.path.

Missing fields arrive as undefined. Use then.field for property paths and array indices; given for JSONPath.

Context Value
context.path Selected value path, including then.field.
context.document.data Original document.
context.document.source Input filename.
context.rule Name, description, severity, resolution, recommendation, selectors, formats.

Unsupported APIs, exceptions, rejected Promises, malformed findings, and timeouts fail execution.

Each document gets a fresh runtime. Initialization runs during loading and per document; exports must be deterministic.

Spectral imports

import { truthy } from '@stoplight/spectral-functions';
import { oas3 } from '@stoplight/spectral-formats';

export default {
  formats: [oas3],
  rules: {
    'title-required': {
      given: '$.info',
      then: { field: 'title', function: truthy }
    }
  }
};
Import Supported exports
@stoplight/spectral-functions truthy, falsy, defined, undefined, pattern, enumeration, length, alphabetical, casing, xor, schema. Native implementations.
@stoplight/spectral-formats oas2, oas3, oas3_0, oas3_1, asyncapi2, asyncapi3.
@stoplight/spectral-core createRulesetFunction, with input and options schemas.

Other exports fail at load time. Native helpers use vacuum’s behavior and messages. Test before migrating.

Extend imported ruleset objects or named rulesets such as spectral:oas. Callable formats also work in aliases.

Test the rules

Set ruleset: rules.mjs in an agent test suite to record execution evidence and module hashes.

vacuum test suite.yaml

Runtime inputs cannot all be captured. Executable rulesets get non-reproducible manifests; bundle export is refused.

Boundaries

  • Local entries only. No remote JavaScript or JavaScript in YAML/JSON extends.
  • No dynamic import() or require().
  • No Node built-ins, native addons, or top-level await. Compile TypeScript first.
  • Export an object, not a factory or Promise.
  • fetch keeps the existing network restrictions.
  • Existing --functions directories still work. JavaScript rulesets do not need one.