Scan rules

116 rules, zero model calls

Every finding in a paniolo scan report comes from a deterministic rule that runs locally — the same tree always gets the same score. Rules are grouped by the dimension they score into; each carries a default severity you can override per repo.

Mechanics

How a rule runs

SurfaceBehavior
Severityerror fails --fail-on error; warn reports without failing the default gate; info is advisory. Any rule can be retuned — or set to off — in rules.
Per-run overrides--rule <id>=<severity> tunes one rule for the invocation; --profile selects a built-in rule profile; --harness restricts to one vendor's surface.
ApplicabilityMost rules always run. Some only apply to intelligence-layer source repos, and one family does network I/O — those only run under the opt-in --external-links flag, never in the default offline scan.
Custom rulescustomRules declares repo-local rules that join the registry — scored and tuned like a built-in.
Unknown ids--strict-config fails the scan when the config names a rule that doesn't exist — a stale id fails loudly instead of silently doing nothing.

Flag-by-flag detail lives in the scan guide; the config fields are in the config reference.

Catalog

Every built-in rule

Generated from the rule registry in @paniolo/cli — regenerate with node scripts/gen-rules-doc.mjs. Where a rule says "Oxc-backed", it runs on parsed TypeScript, not text matching.

Guardrails 58 rules

Security, permissions, CI hygiene, and the probabilistic/deterministic boundary.

RuleSeverityWhat it checks
actions-sha-pinnedwarnflags workflow actions pinned to mutable tags instead of commit SHAs.
agent-resource-budget-capsinfoflags an agent/tool surface with no declared resource caps (max iterations, cost, or rate limit).
boundary.no-assert-mocked-returnwarnOxc-backed boundary rule for mock-return assertions in test files.
boundary.no-cross-package-deep-importwarnOxc-backed boundary rule for workspace cross-package import shape.
boundary.no-disable-in-testswarnOxc-backed boundary rule for lint-disable comments in test files.
boundary.no-dual-named-and-default-exportwarnOxc-backed boundary rule for the one-canonical-export-path convention.
boundary.no-empty-arrangewarnOxc-backed boundary rule for empty // Arrange comments in test files.
boundary.no-module-load-only-testwarnOxc-backed boundary rule for import-success-only unit tests.
boundary.no-reactelement-importwarnOxc-backed boundary rule for the ReactElement ambient-type convention.
boundary.no-runtime-test-for-type-only-modulewarnBoundary rule for runtime tests conventionally paired with type-only modules.
boundary.no-tautological-assertionwarnOxc-backed boundary rule for assertions that prove only their own literals.
boundary.no-test-for-constants-only-modulewarnBoundary rule for tests conventionally paired with constants-only modules.
boundary.no-test-of-test-utilitywarnBoundary rule for dedicated tests of test-only infrastructure.
boundary.no-void-async-iifewarnOxc-backed boundary rule banning void <async fn>() fire-and-forget invocations, ported from the ESLint no-restricted-syntax selector UnaryExpression[operator='void'] > CallExpression[callee.async=true].
boundary.require-aaa-patternwarnOxc-backed boundary rule requiring Arrange/Act/Assert comments in tests.
boundary.require-each-type-paramwarnOxc-backed boundary rule requiring a TypeScript type parameter on it.each, test.each, and describe.each calls.
boundary.require-own-file-for-long-functionwarnOxc-backed boundary rule for module-scope function file splits.
boundary.require-useeffect-commentwarnOxc-backed boundary rule requiring a comment above every useEffect.
ci-enforcement-gatesinfoflags repos whose CI workflows never run a typecheck/lint/static-analysis gate.
ci-guidance-lintinfoflags repos whose CI never runs a guidance-maintenance gate (markdown lint, link check, self-scan).
ci-validation-gatesinfoflags repos whose CI workflows never run a test command.
claude-hooks-validerrorvalidates .claude/settings*.json hook shape and script references.
codex-agents-validerrorchecks that every .codex/agents/*.toml thin wrapper stays consistent with its shared .agents/agents/*.agent.md definition, and that every shared agent has a wrapper.
codex-hook-countserrorchecks that .codex/hooks.json wires the committed number of hooks per event group, so a refactor cannot silently drop the qmd prompt-context, maintenance, or stop hooks.
codex-hooks-validerrorvalidates .codex/hooks.json shape and script references.
comment-obvious-name-repeatinfoflags symbol comments whose first sentence only restates the symbol name and kind.
correction-loop-documentedinfoflags repos with no durable AI correction-loop signal across scripts, PR templates, or CI.
cursor-hook-countserrorchecks that .cursor/hooks.json wires the committed number of native handlers per event, so a refactor cannot silently drop the session guidance, shell guard, edit tracking, or stop lint gate.
custom-diagnostics-presentinfoflags repos with no repo-specific lint/static-analysis rules beyond a generic lint gate.
editor-hooks-validerrorvalidates .github/hooks/*.json (VS Code custom-agent format) and .cursor/hooks.json (Cursor native format): each must be valid JSON, and every scripts/…​.ts path referenced by a hook command must exist on disk.
env-files-gitignoredwarnflags committed .env* files unless they're gitignored.
escalation-protocol-discoverabilityinfoflags guidance that documents no epistemic-escalation protocol (asking for clarification on missing, ambiguous, or contradictory specs).
focused-test-commands-presentinfoflags repos with no discoverable narrower validation command than the full suite.
high-impact-action-confirmationwarnflags source that performs high-impact actions (deletion, payment, force-push, deploy, external send) with no human-in-the-loop confirmation or escalation in evidence.
hook-launcher-portableerrorchecks that committed hook configs do not name a platform-specific launcher path.
hook-no-network-exfilerrorflags hook scripts that make a network call to a non-local host.
hook-stop-circuit-breakerwarnflags Stop hooks that never check stop_hook_active before re-blocking.
jsdoc-enforcement-presentinfoflags repos where JSDoc comment standards are not documented and enforced deterministically.
jsdoc-no-typescript-typeswarnJSDoc comment policy rules over shared code-symbol records.
jsdoc-spacingwarnflags a JSDoc block whose preceding line breaks the repository's comment-spacing convention.
lint-gate-presentinfoflags repos with no discoverable lint/static-analysis gate.
llm-output-schema-validatedwarnflags source files that consume LLM/tool output without a schema validator in scope.
memory-write-provenanceinfoflags a persistent-memory-write surface with no provenance/trust tagging or re-validation in evidence.
model-interface-pinnedwarnflags floating -latest model-id aliases in application source/config.
no-dangerous-auto-approveerrorflags .claude/settings*.json files that set a bypass defaultMode or auto-approve a dangerous tool with a blanket allow entry.
no-pull-request-targeterrorflags workflows triggered by pull_request_target, which runs with repo secrets against untrusted PR code.
paniolo-state-gitignoredwarnflags a present .paniolo/ that no ignore pattern covers.
rustdoc-public-itemswarnRustdoc comment policy rules over shared code-symbol records.
secret-scanning-configuredwarnflags repos with no detectable secret-scanning configuration.
sensitive-stringswarnflags lines containing sensitive strings that must not be committed, such as hardcoded home-directory paths that leak a username.
skill-destructive-verb-confirmationinfoflags skills/**/SKILL.md files that instruct a destructive action without a nearby confirmation / staging / dry-run cue in the same markdown section.
skill-side-effect-disclosureinfoflags skills/**/SKILL.md files whose body describes state mutations (writing files, committing, pushing, mutating config) while the frontmatter description: gives no hint that the skill leaves state behind.
strict-typecheck-presentinfoflags repos with no discoverable strict typecheck/static-analysis gate.
test-gates-presentinfoflags repos with no discoverable unit/integration/E2E validation gate.
tool-allowlist-inventoryinfoflags a repo that references MCP/tool servers but declares no explicit, pinned tool allowlist.
tool-contract-tests-presentinfoflags a repo that declares model-callable tools but whose tests never exercise tool-call argument validation or error responses.
untrusted-input-action-boundarywarnflags source that both ingests untrusted content and takes actions with no sanitization, validation, or confirmation in evidence.
vscode-custom-hookswarnwarns when .github/hooks/ exists but chat.useCustomAgentHooks isn't enabled in .vscode/settings.json.

Maintainability 27 rules

Size budgets, structure, duplication, and upkeep of guidance files.

RuleSeverityWhat it checks
agent-frontmattererrorflags agents/**/*.agent.md files missing YAML frontmatter or the required name/description fields.
agent-line-countwarnwarns when an agents/**/*.agent.md file exceeds the line budget.
code-layoutwarnflags flat module sprawl and junk-drawer feature folder names so the legacy harness check-code-layout script can move into scan.
dead-codewarnRust-native project graph analysis for JavaScript and TypeScript, backed by Fallow.
doc-fragment-linkswarnflags outbound path.md#anchor fragment links in AI-context files.
emphasis-keyword-densityinfoflags instruction files that lean on all-caps emphasis keywords.
external-links-resolvewarnopt-in **network** rule flagging dead external http(s) URLs in the guidance corpus.
github-skills-shadowwarnforbidden-legacy-paths — flags markdown references to known-removed or shadow guidance paths (e.g.
guidance-links-resolvewarnflags internal markdown links in guidance files whose target does not resolve.
guidance-maintenance-scriptinfoflags repos with detectable project context but no discoverable guidance-maintenance script (e.g.
identity-language-absentinfoflags instruction files that contain identity / roleplay filler the model would follow anyway.
link-fragments-resolvewarnflags markdown links whose #fragment does not resolve to a heading or explicit <a id> anchor in the target file.
local-context-patternsinfoflags repos with detectable guidance or memory context but no documented local-context conventions (naming and comment conventions, or nested AGENTS.md files).
no-duplicate-agent-treeserrorflags duplicate or legacy agent trees: - .github/agents/ when a canonical agents/ or .agents/agents/ tree exists - agents/ root when .agents/agents/ is the canonical location (June 2026 layout)
no-file-scheme-linkswarnflags markdown links whose href uses a file: scheme (for example the VS Code file URIs that AI tools sometimes emit).
no-heading-anchorswarnflags standalone HTML heading anchors (<a id="…"></a> alone on a line) in skills and the shared rules file.
pr-template-ai-harness-checkinfoflags repos with detectable project context but no PR template reminder to update durable AI harness assets (rules, docs, skills, tests, diagnostics).
rust-first-harness-boundarywarnkeeps Rust-first harness repos from growing legacy TypeScript/JavaScript product surfaces without making the current retirement backlog noisy.
skill-countinfoa sanity-ceiling smell test for runaway skill-library growth.
skill-description-budgetwarnflags skills/**/SKILL.md frontmatter whose combined description + when_to_use text is near or over Claude Code's 1,536-character listing cap.
skill-fallback-guidanceinfoflags skills/**/SKILL.md files that name an external dependency (a CLI, MCP server, binary, or another tool) without any guidance on what to do when that dependency is missing or fails.
skill-invocation-gate-consistencyinfoflags skills/**/SKILL.md files whose invocation gates (disable-model-invocation, user-invocable) look inconsistent with whether the body reads as a task or as reference material.
skill-line-countwarnwarns when a skills/**/SKILL.md file exceeds the line budget.
skill-missing-do-notinfoflags skills/**/SKILL.md files that lack a ## Do Not section.
skill-missing-referencesinfoflags skills/**/SKILL.md files that lack a ## References section.
wiki-authoring-links-resolvewarnflags AI-context links to a configured wiki page (<wiki>/wiki/<slug>.md) whose target file does not exist on disk.
wiki-link-stylewarnflags markdown references to a configured wiki page by raw path (<wiki>/wiki/<slug>.md) that should instead use wikilink ([[slug]]) syntax, so the reference participates in the wiki graph.

Discoverability 12 rules

Whether agents can find what exists — indexes, mentions, registration.

RuleSeverityWhat it checks
agents-md-mentions-skillsinfoflags AGENTS.md with no pointer to skill discovery when root skills/ is non-empty.
claude-agent-routinginfoflags CLAUDE.md with no Agent Routing table when Claude is detected.
memory-docs-indexedinfoflags durable memory docs with no index and no search surface.
qmd-script-presentinfoflags repos with skills/ or 2+ .agents/ files and no qmd (or equivalent) doc-search script.
skill-boundary-languageinfoflags complex skills/**/SKILL.md files that lack routing exclusion language.
skill-composition-discoverabilityinfowarns when a repo has several skills but cross-references between them are rare, suggesting a flat/monolithic skill set with no widely-declared composition structure.
skill-dependency-declarationinfoflags skills/**/SKILL.md files whose body contains ordering/prerequisite language without declaring the dependency structurally (a dependsOn:-style frontmatter field or a ## Use When section).
skill-description-overlapinfoflags pairs of skills/**/SKILL.md files whose frontmatter description: fields are near-duplicates under token Jaccard similarity.
skill-doc-deep-linksinfoflags substantial skills/**/SKILL.md files that inline detail instead of deep-linking into durable guidance under .agents/, docs/, or wiki/ (llm-wiki).
skill-index-orphansinfoflags root skills that are not mentioned in the skill slug index.
skill-self-containederrorshipped paniolo-* skills must contain no [[wikilink]] syntax.
skills-indexinfoflags a non-empty root skills/ with no skill slug index.

Layering 7 rules

What loads always vs on demand — context budget discipline.

RuleSeverityWhat it checks
adapter-line-countwarnwarns when any root adapter file (CLAUDE.md, GEMINI.md, .github/copilot-instructions.md, DEVIN.md, etc.) exceeds the line budget.
adapter-points-to-sharedwarnwarns when a present root adapter (CLAUDE.md, GEMINI.md, .github/copilot-instructions.md) doesn't reference shared AGENTS.md or canonical rules layers.
agents-md-line-countwarnwarns when AGENTS.md exceeds the line budget.
no-duplicate-skill-treeserrorflags alternate skill trees that duplicate the canonical .agents/skills/ tree.
rules-doc-line-countwarnwarns when the shared .agents/rules.md exceeds the line budget.
shared-agents-mdwarnwarns when AGENTS.md is missing.
shared-rules-docwarnwarns when no canonical rules doc is present.

Reliability 4 rules

Contracts, tests, and pinning that keep agent behavior predictable.

RuleSeverityWhat it checks
skill-eval-artifact-completenesswarnflags skills/**/SKILL.md trees that advertise an evals/ harness (skill-creator / agentskills.io convention) but ship a missing, invalid, empty, or fixture-broken evals/evals.json.
skill-frontmattererrorflags skills/**/SKILL.md files missing YAML frontmatter or the required name/description fields.
skill-frontmatter-yamlerrorflags skills/**/SKILL.md frontmatter blocks that fail to parse as YAML, parse to a non-mapping value, or have a name/description field of the wrong type.
skill-link-integrityerrorflags skill-to-skill markdown links whose target SKILL.md path does not exist in the repo.

Sharing 3 rules

One source of truth, wired into each adapter — not copied into each.

RuleSeverityWhat it checks
adapter-content-duplicationwarnflags root adapter text that duplicates blocks from the canonical .agents/rules.md.
adapter-context-budgetinfoflags always-loaded instruction files that exceed the per-file line budget.
always-loaded-budgetinfoflags detected harnesses whose total always-loaded context exceeds the recommended line budget.

Harness wiring 3 rules

Vendor-specific plumbing — hooks, adapter locations, per-tool config.

RuleSeverityWhat it checks
devin-config-presentwarnwarns when Devin CLI is detected but .devin/config.json is absent or does not set read_config_from.claude: true.
vscode-agents-locationwarnwarns when .vscode/settings.json doesn't configure chat.agentFilesLocations to point at agents/ or .agents/agents/ (the consolidated layout introduced June 2026).
vscode-skills-locationwarnwarns when .vscode/settings.json doesn't configure chat.agentSkillsLocations to point at the configured skills directory.

Consistency 1 rule

Same meaning, same shape, everywhere it appears.

RuleSeverityWhat it checks
skill-link-stylewarnenforces one configured link style for skill-to-skill references inside SKILL.md files.

Readability 1 rule

Prose quality of the guidance itself.

RuleSeverityWhat it checks
skill-max-line-lengthwarnflags prose lines in skills/**/SKILL.md files that exceed a configurable character budget.