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
pnpm add -D eslint @graphorin/eslint-pluginUsage (ESLint flat config — eslint.config.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:
import graphorin from '@graphorin/eslint-plugin';
export default [
graphorin.configs.recommended,
];Rules
| Rule | Status |
|---|---|
tool-description-required | Active. Flags tool({...}) registrations whose description is missing, shorter than 20 characters, or a placeholder value ('TODO', 'FIXME', 'tbd', 'description', 'placeholder'). |
tool-examples-recommended | Active. Flags missing or empty examples arrays and rejects more than the documented upper bound (5). |
tool-parameter-naming | Active. 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-unwrap | Active. 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-deps | Active. Flags Agent.toTool({ inheritSecrets: [...] }) calls whose allowlist is non-empty and lacks an // rb-24-justification: <reason> comment. |
provider-middleware-order | Active. Lint-time enforcement of the canonical withTracing → withRetry → withRateLimit → withCostLimit → withCostTracking → withFallback → withRedaction ordering. |
no-implicit-network-call | Active. 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-aliases | Active. 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-exec | Active. Flags tool({ execute }) functions that do not reference signal so long-running tools always propagate the cancellation contract. |
no-console-in-public-api | Scaffold (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:
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
| Interface | Description |
|---|---|
| DiscoveredTool | - |
| LintFinding | - |
| ToolGraderScore | - |
Type Aliases
| Type Alias | Description |
|---|---|
| LintFindingKind | - |
Variables
| Variable | Description |
|---|---|
| AMBIGUOUS_PARAMETER_NAMES | Generic 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_TAGS | Tag 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_DESCRIPTIONS | Placeholder values the description-required rule treats as non-descriptions. |
| rules | - |
| VERSION | - |
Functions
| Function | Description |
|---|---|
| discoverToolCallsInSource | Discover every tool({...}) invocation in a source string. The returned findings are stable + frozen so callers can pass them straight into a JSON report. |
| gradeTool | Compute 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). |
| runToolRules | Run 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(...). |