Skip to content

The doctor contract

Metadata, shared analysis, and inspectable findings for a doctor and its fixtures.

Updated View as Markdown

A doctor is a single JS file. It exports a meta object and a doctor(ctx) function. Companion fixtures describe the cases used to verify it.

Here’s what the metadata for a doctor looks like:

export const meta = {
  id: "refresh-session",
  description: "Direct discarded session refresh promises.",
  severity: "warning",
  blindSpots: [
    "Only direct named imports from @acme/session are recognized.",
    "Stored promises and wrapper calls are not followed.",
    "Without call analysis this check does not run.",
  ],
  checks: [{
    id: "discarded-refresh",
    description: "The session refresh call's result is discarded.",
    severity: "warning",
    revision: 1,
    needs: ["calls"],
    onUnknown: "skip",
    reportingUnit: "occurrence",
    claim: "A direct named refreshSession import from @acme/session is called as a discarded expression.",
    lookalikes: ["Awaited, returned, passed, or stored results", "Shadowed local functions"],
    impact: "Discarding this promise can leave refresh failures unhandled.",
    why: "The identified package call is a standalone discarded expression.",
    fix: "Await or return this promise where appropriate for the caller's contract.",
  }],
};

This metadata accompanies the complete implementation and fixtures in Writing your first doctor. That example assumes the named package export returns a promise; metadata alone does not establish it.

The confinement

The runtime gives the doctor a read-only context and nothing more.

Doctors run under Node’s permission model: file writes, subprocesses, and native addons are denied by Node itself, and an import guard refuses every module a doctor tries to reach. Network globals are deleted before doctor code runs, and a checker scans the doctor file for network calls. Nothing phones home.

Check fields

Field What it is
id Stable check name; appears as doctor/check-id
description The heading shown for each finding
severity error, warning, or info; severity does not establish certainty
revision Bump when the check’s meaning changes; cosmetic edits keep it
claim The observable condition the check states. Required to certify
lookalikes Shapes that look like the claim but are fine
needs Required analysis capabilities, such as ["calls"]; declare these when using optional analysis
onUnknown "narrow" or "skip" when required analysis is unavailable; implement and test this behavior
reportingUnit occurrence, file, or project — what one finding covers
impact / why / fix The explanation carried into every report and JSON scan

The claim is the load-bearing field. A check without a claim cannot be certified, because eloquent impact prose is not a testable statement. A nonempty claim is not proof that the implementation establishes it. Verification also requires lookalikes, and an onUnknown policy when needs is declared. Declare a reporting unit on new checks and inspect skipped coverage. More on this in honest checks.

Report an inspectable finding

evidence belongs to an emitted finding, not the check metadata:

ctx.report.finding({
  rule: "discarded-refresh",
  file,
  line: call.line,
  column: call.column,
  evidence: { endLine: call.endLine, endColumn: call.endColumn },
});

Lines are one-based and columns are zero-based. Supply the expression’s end position for multiline evidence. Distinct occurrences on one line need distinct columns; location and evidence help reviewers inspect the claimed operation.

Doctors receive shared structural and binding analysis through ctx. Use these facts to establish identity and scope; keep framework semantics in the doctor. Do not import a parser or create a private text-based substitute for semantic facts. See testing and evaluating doctors for location witnesses, unavailable-analysis fixtures, and independent evaluation.

Where doctors live

Three locations, in priority order:

  1. ./doctors/ in the repo being scanned
  2. ~/.any-doctor/doctors/ (global, --global when generating)
  3. the bundled pack (lowest priority)

Fixture files (*.fixtures.mjs) beside a doctor are its test data, not target source — scans skip them.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close