Skip to main content
RuleContext is the supported interface between a custom rule and Strata’s analysis engine. Import public protocols, handles, locations, facts, and dependency models from strata, never internal package paths.

Analysis zones

Current-file facts

ctx.facts.annotations()
ctx.facts.comments()
ctx.facts.dataclasses()
ctx.facts.complex_comprehensions()
ctx.facts.function_conditionals()
ctx.facts.functions()
ctx.facts.function_contracts()
ctx.facts.hygiene()
ctx.facts.meaningful_returns(name_patterns=("validate_*",))
ctx.facts.module_declarations()
ctx.facts.outer_state_mutations()
ctx.facts.parameter_mutations()
ctx.facts.project_calls()
ctx.facts.project_functions()
ctx.facts.references()
ctx.facts.test_functions()
ctx.facts.test_module()

Project and filesystem

ctx.project.analysis(requester=ctx.path, path=other_path)
ctx.project.dataclasses(requester=ctx.path, path=other_path)
ctx.project.module_function(
    requester=ctx.path,
    module_name="my_package.jobs",
    function_name="run",
)
ctx.project.exists(requester=ctx.path, path=other_path)
ctx.project.is_file(requester=ctx.path, path=other_path)
ctx.project.is_dir(requester=ctx.path, path=other_path)
ctx.project.directory_entries(requester=ctx.path, path=directory)
ctx.project.glob(requester=ctx.path, path=directory, pattern="*.py", recursive=False)
ctx.project.python_anchor(requester=ctx.path, path=directory)
ctx.project.dependencies()
ctx.project.dependencies_for(requester=ctx.path)
Every project and filesystem query records its input for cache invalidation. Pass the file whose result depends on the query as requester, normally ctx.path.

Text, syntax, and relationships

ctx.text.source
ctx.text.line(line_number)
ctx.text.slice(source_range)

ctx.syntax.handles(kind=None)
ctx.syntax.kind(handle)
ctx.syntax.range(handle)

ctx.relations.parent(handle)
ctx.relations.children(handle)
ctx.relations.ancestors(handle)
The corresponding public protocols are FactAnalysis, ProjectAnalysis, TextAnalysis, SyntaxAnalysis, and RelationAnalysis. SyntaxHandle, SourceLocation, SourcePosition, SourceRange, fact models, and dependency models are also exported from strata.

Fault construction

ctx.fault(node=node, message=None, remediation=None)
ctx.fault_at(location=location, message=None, remediation=None)
ctx.fault_for(path=path, line=1, column=0, message=None, remediation=None)
ctx.path_fault(path=None, message=None, remediation=None)
Omitted messages and remediations use the rule’s declared envelope values.

Position and roles

ctx.path
ctx.repo_root
ctx.source
ctx.relative_parts()
ctx.repo_relative_parts()
ctx.scope_root()
ctx.scope_roots(ctx.scope())
ctx.module_parts()
ctx.role_of(path=None)
ctx.in_role("main")
ctx.is_entry_module()
ctx.is_main_module()
ctx.domain()
ctx.subdomain()
ctx.scope()
These values derive from configured roots and scopes, not hardcoded package names.

AST helpers

ctx.nodes(ast.Call)
ctx.call_name(call)
ctx.base_name(expr)
ctx.top_level_functions(module)
ctx.non_docstring_body(module)
ctx.distinct_callees(fn)
ctx.assigned_locals(fn)
ctx.parameter_names(fn)
ctx.complex_comprehensions()
ctx.inside_loop(node)
Prefer ctx.nodes() over ast.walk(module) for module-wide scans so cooperating rules share Strata’s single traversal. Direct AST walking remains supported when a rule needs unrestricted syntax access.

Configuration

ctx.threshold(name=Threshold.MAX_STATEMENTS)
ctx.contracts()
threshold() returns the value effective for the current file after global, per-role, and path-scoped overrides.