Skip to content

Graphorin API reference v0.1.0


Graphorin API reference / @graphorin/eslint-plugin

@graphorin/eslint-plugin

ESLint rules for projects that build on Graphorin.

  • Status: v0.1.0 — final Phase 16 ruleset.
  • License: MIT — © 2026 Oleksiy Stepurenko.
  • Engines: Node.js 22+ (ESM only).
  • Peer dependency: eslint >= 9.

Installation

bash
pnpm add -D eslint @graphorin/eslint-plugin

Usage (ESLint flat config — eslint.config.js)

js
import graphorin from '@graphorin/eslint-plugin';

export default [
  {
    plugins: { '@graphorin': graphorin },
    rules: {
      '@graphorin/tool-description-required': 'error',
      '@graphorin/tool-examples-recommended': 'warn',
      '@graphorin/tool-parameter-naming': 'warn',
      '@graphorin/no-secret-unwrap': 'error',
      '@graphorin/no-secret-in-deps': 'error',
      '@graphorin/no-implicit-network-call': 'error',
      '@graphorin/no-third-party-workflow-aliases': 'error',
      '@graphorin/provider-middleware-order': 'error',
      '@graphorin/no-bare-tool-exec': 'warn',
    },
  },
];

The bundled recommended config wires every active rule at the severities documented below; consumers can extend it directly:

js
import graphorin from '@graphorin/eslint-plugin';

export default [
  graphorin.configs.recommended,
];

Rules

RuleStatus
tool-description-requiredActive. Flags tool({...}) registrations whose description is missing, shorter than 20 characters, or a placeholder value ('TODO', 'FIXME', 'tbd', 'description', 'placeholder').
tool-examples-recommendedActive. Flags missing or empty examples arrays and rejects more than the documented upper bound (5).
tool-parameter-namingActive. Flags ambiguous single-word parameter names (user, id, name, value, data, input, output, result, to, from, key, field) and numeric-suffix names (arg1, param2) on inputSchema: z.object({ ... }). Per-tool opt-out via tags: ['experimental'] or tags: ['legacy'].
no-secret-unwrapActive. Flags .unwrap() and .reveal() calls on SecretValue-shaped expressions. .unwrap() is reported as 'error' regardless of comments (the method is @deprecated); .reveal() honours the // graphorin-allow-secret-unwrap: <reason> opt-out.
no-secret-in-depsActive. Flags Agent.toTool({ inheritSecrets: [...] }) calls whose allowlist is non-empty and lacks an // rb-24-justification: <reason> comment.
provider-middleware-orderActive. Lint-time enforcement of the canonical withTracing → withRetry → withRateLimit → withCostLimit → withCostTracking → withFallback → withRedaction ordering.
no-implicit-network-callActive. Flags bare fetch(...) / axios.get(...) / https.request(...) / new XMLHttpRequest() invocations in @graphorin/* framework code without the explicit // graphorin-allow-network: <reason> opt-out.
no-third-party-workflow-aliasesActive. Flags identifiers that mirror third-party-library workflow primitives in the @graphorin/workflow package's source so the framework keeps its own naming.
no-bare-tool-execActive. Flags tool({ execute }) functions that do not reference signal so long-running tools always propagate the cancellation contract.
no-console-in-public-apiScaffold (no-op). Will flag console.* calls in code that is part of a package's public surface; activates after the v0.1 public-API freeze.

Programmatic discovery (single source of truth)

The three tool-* rules are also exposed as plain helpers so graphorin tools lint reuses the same logic without re-importing through the ESLint runtime:

ts
import {
  AMBIGUOUS_PARAMETER_NAMES,
  discoverToolCallsInSource,
  gradeTool,
  PARAMETER_NAMING_OPT_OUT_TAGS,
  PLACEHOLDER_DESCRIPTIONS,
  runToolRules,
} from '@graphorin/eslint-plugin';

const source = await readFile('src/tools/send-email.ts', 'utf8');
const tools = discoverToolCallsInSource('src/tools/send-email.ts', source);
for (const tool of tools) {
  const findings = runToolRules(tool);
  const score = gradeTool(tool, findings);
  console.log(`${tool.name}: ${score.score}/100`);
}

Versioning

@graphorin/eslint-plugin follows the same lockstep release as the rest of the @graphorin/* packages while the framework is on the 0.x line. Once Graphorin reaches 1.0, the plugin will move to its own release cadence.


Graphorin · v0.1.0 · MIT License · © 2026 Oleksiy Stepurenko · https://github.com/o-stepper/graphorin

@graphorin/eslint-plugin — ESLint plugin for projects that build on the Graphorin framework.

Phase 16 final ruleset:

  • no-console-in-public-api — scaffold (no-op).
  • no-secret-unwrap — DEC-020 / ADR-026. Active.
  • no-secret-in-deps — DEC-137. Active.
  • provider-middleware-order — DEC-145 / ADR-039. Active.
  • no-implicit-network-call — DEC-154 / ADR-041. Active.
  • no-third-party-workflow-aliases — DEC-019 / ADR-029. Active.
  • no-bare-tool-exec — principle 3 / DEC-143. Active.
  • tool-description-required — Active.
  • tool-examples-recommended — Active.
  • tool-parameter-naming — Active.

no-console-in-public-api is intentionally a no-op for v0.1 — the full implementation is a stylistic refinement that depends on the post-v0.1 public-API surface freeze and does not affect the security guarantees this plugin enforces.

Interfaces

InterfaceDescription
DiscoveredTool-
LintFinding-
ToolGraderScore-

Type Aliases

Type AliasDescription
LintFindingKind-

Variables

VariableDescription
AMBIGUOUS_PARAMETER_NAMESGeneric identifiers the parameter-naming rule flags as ambiguous. Tools whose inputSchema references only specific identifiers (e.g. userId, recipientEmail, apiKey) get full credit on the naming axis.
configs-
default-
meta-
PARAMETER_NAMING_OPT_OUT_TAGSTag values that, when present in a tool's tags: [...] literal, suppress the parameter-naming rule for that tool. The opt-out exists so operators can defer the rename for a long tail of pre-RB-49 tools while the framework migrates without breaking calling code.
PLACEHOLDER_DESCRIPTIONSPlaceholder values the description-required rule treats as non-descriptions.
rules-
VERSION-

Functions

FunctionDescription
discoverToolCallsInSourceDiscover every tool({...}) invocation in a source string. The returned findings are stable + frozen so callers can pass them straight into a JSON report.
gradeToolCompute the per-tool grader score (0..100). Each axis is gated by the findings produced for that axis. The rubric is calibrated against the RB-49 fixture catalog (wellDescribedTool -> 82, placeholderDescriptionTool -> 20, examplesPiiTool -> 61).
runToolRulesRun the three RB-49 rules against a discovered tool and return the findings. The CLI grader maps these findings into per-axis scores; the ESLint rules forward them to context.report(...).