Skip to main content
Glama

Run Rego tests across multiple roots

rego_test_multiroot

Run opa test once per test root and aggregate results to avoid package conflicts in repos with multiple independent Rego namespaces. Supports explicit roots or auto-discovered leaf roots with shared paths.

Instructions

Run opa test once per root and aggregate results. Solves the package-conflict problem that occurs when opa test . is run on a repo with multiple independent package namespaces (OPA issue #4724). Two modes: explicit (supply root list with optional per-root include paths for shared libraries) and scan (auto-discover leaf test roots using the leaf rule -- a directory is a root only if it directly contains *_test.rego files and none of its eligible subdirectories do, preventing OPA's automatic recursion from double-running tests). Use sharedPaths in scan mode to add shared library directories to every root's invocation without including them in discovery. Coverage and threshold work per-root; overallCoveragePct is the mean across roots that have coverage data.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rootsNoExplicit list of test root directories. Use when roots are known upfront or when scan mode cannot determine the correct roots. Mutually exclusive with `scanDir`.
scanDirNoTop-level directory to scan for test roots. Uses the leaf rule: a directory is a root only if it directly contains `*_test.rego` files and none of its eligible subdirectories do. Mutually exclusive with `roots`.
verboseNoEmit per-test pass/fail details for each root.
coverageNoInclude per-line coverage data per root. Switches output to coverage-report mode: test record counts are not available, but `coverage`, `coveragePct`, and `overallCoveragePct` fields are populated.
maxDepthNoMaximum directory depth to scan. Default: 10. Only used with `scanDir`.
maxRootsNoMaximum number of test roots allowed. Returns INVALID_INPUT if scan finds more. Default: 50. Only used with `scanDir`.
thresholdNoMinimum coverage percentage required per root (0-100). Roots below threshold have `thresholdMet: false` in their result. Implicitly enables coverage-report output mode.
varValuesNoInclude local variable bindings in trace output (`--var-values`). Only useful with `verbose: true`.
runPatternNoRun only tests whose names match this regular expression (passed as `--run` to each root).
sharedPathsNoPaths added to every root's `opa test` invocation and excluded from auto-discovery. Use for shared library directories that all roots import from.
v0CompatibleNoRead the policy as Rego v0 (`--v0-compatible`), the syntax OPA used before 1.0: rules without `if`, partial sets as `deny[msg] { ... }`. Needed for a policy that has not been migrated, which OPA 1.x otherwise refuses to load. Where the tool also takes a query, the query is read as v0 too, with the future keywords imported so `in`, `every` and `some x in` still work in it.
ignorePatternsNoAdditional directory name patterns to skip during scan (e.g., ["vendor", "*.generated"]). Supports `*` wildcards. Only used with `scanDir`.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv0.8.0
    • changedInput schema / properties / v0Compatible / description
      Previous value: -"Read the policy as Rego v0 (`--v0-compatible`), the syntax OPA used before 1.0: rules without `if`, partial sets as `deny[msg] { ... }`. Needed for a policy that has not been migrated, which OPA 1.x otherwise refuses to load."New value: +"Read the policy as Rego v0 (`--v0-compatible`), the syntax OPA used before 1.0: rules without `if`, partial sets as `deny[msg] { ... }`. Needed for a policy that has not been migrated, which OPA 1.x otherwise refuses to load. Where the tool also takes a query, the query is read as v0 too, with the future keywords imported so `in`, `every` and `some x in` still work in it."
  2. Changed1 schema field changedv0.7.0
    • addedInput schema / properties / v0Compatible
      Added value: +{
      +  "description": "Read the policy as Rego v0 (`--v0-compatible`), the syntax OPA used before 1.0: rules without `if`, partial sets as `deny[msg] { ... }`. Needed for a policy that has not been migrated, which OPA 1.x otherwise refuses to load.",
      +  "type": "boolean"
      +}
  3. Addedv0.1.17

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, openWorldHint=true), the description discloses substantial behavior: the leaf rule and why it prevents OPA's recursion from double-running tests, that coverage/threshold apply per-root while overallCoveragePct is a mean over roots with coverage data, and that coverage switches the output mode. These are non-obvious execution semantics an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and the conflict it solves are front-loaded, and each subsequent sentence adds distinct information (modes, leaf rule, sharedPaths, coverage aggregation). It is dense and slightly long, with minor overlap between the description and schema descriptions, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does so: it names the per-root result fields (thresholdMet), overallCoveragePct, and how coverage mode changes available output. For a 12-parameter, zero-required tool with nested root objects, it is complete enough to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents each field (baseline 3). The description still adds cross-parameter meaning the schema cannot: mutual exclusivity of `roots`/`scanDir`, mode-specific relevance of `sharedPaths` and scan-only params, and the fact that `threshold` implicitly enables coverage-report mode.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource (run `opa test` per root and aggregate) and immediately differentiates from the plain `rego_test` sibling by naming the exact problem it solves (package-conflict on multi-namespace repos, OPA issue #4724). An agent can tell exactly what this does and why it exists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly explains the two operational modes (explicit vs scan) and when to use `sharedPaths` in scan mode, giving strong context. However, it never explicitly contrasts with the sibling `rego_test` tool ('use this instead when...'), leaving that selection to inference from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.