A Dialect interprets provider instances. Keep its source beside the project while authoring, pass --dialect for one run, and add it to rootform.lock only after reviewing the resulting facts. This example uses random_pet to keep the plan small; the same sequence applies to a provider-specific Dialect with architectural Contexts and Relations.
Prerequisites: Rootform, Terraform, and a project directory you control. OpenTofu users run the Terraform commands with tofu. Run commands below from that directory. The plan JSON and saved plan can carry cleartext secrets in a real project; keep them out of Git. Plan inputs gives the complete export and protection procedure.
-
Use this small project and Dialect source to observe one interpretation:
Project files Files.├── main.tf└── dialects/└── network-review/└── dialect.rf.hclmain.tf HCLterraform {required_providers {random = {source = "hashicorp/random"version = "= 3.9.1"}}}resource "random_pet" "service" {length = 2}dialects/network-review/dialect.rf.hcl RFdialect "network-review" {version = "0.1.0"provider "hashicorp/random" {version = "= 3.9.1"}}concept "generated-identifier" {description = "An identifier generated for a service."}rule "service-name" {match {kind = "resource"type = "random_pet"}as = concept.generated-identifier}The manifest binds the provider and the Rule identifies eligible instances.
asgives an interpreted instance a Concept; this example emits no Context or Relation. Write a Dialect explains Rules, endpoint identity, null handling, and evidence tests. -
Produce a saved plan and its JSON export. Rootform reads the completed export; it never runs Terraform or contacts the provider:
Shellterraform initterraform plan -out=plan.tfplanterraform show -json plan.tfplan > plan.jsonTry the source for this run without changing the project selection:
Shellrootform run plan.json --plan-file plan.tfplan --require-enrichment \--dialect ./dialects/network-review --no-serve -o analysis.jsonExcerpt from analysis summary OUTPUTPlan analyzedEnrichment Saved plan paired with this plan JSON (1 module)ArchitectureInstances 1Interpreted 1Facts none determinedThe instance is interpreted, while no facts are determined because the Rule only classifies it. Inspect the Form or
rootform explain instance random_pet.service --input analysis.jsonwhen the result differs.--dialectcompiles current source each run and never writes the lock. -
Check the Dialect source and show the Rule before recording a golden:
Shellrootform validate dialects ./dialects/network-reviewrootform show network-review.rule.service-name \--dialect ./dialects/network-reviewExcerpt from definition OUTPUTnetwork-review.rule.service-nameMatches resource "random_pet"Produces network-review.concept.generated-identifierDefined dialect.rf.hcl:13validatecompiles the source;showconfirms the selected Rule's match and output. Neither proves what a particular plan instance did. Keep a fixture for that proof:Dialect fixture Filesfixtures/network/├── plan.json├── plan.tfplan└── analysis.goldenCopy the plan pair to the fixture. Record a reviewed golden once with
rootform test ./fixtures --dialect ./dialects/network-review --update; then run the ordinary test after each Rule change:Shellrootform test ./fixtures --dialect ./dialects/network-reviewFixture result OUTPUTTests passed1 caseThe test analyzes
plan.json, verifies the adjacent saved plan, and compares the resulting Form withanalysis.golden. A mismatch is a review signal: inspect changed interpretations, facts, closures, and diagnostics before updating the golden. Test and validate covers fixture behavior. -
Once its result is right, select it for this project:
Shellrootform add dialects ./dialects/network-reviewSelection result OUTPUTrootform.lock updatedadd Dialect network-review 0.1.0 (dialects/network-review)The lock records the owner, version, digest, and project-relative local path. Commit it with Dialect source and reviewed fixture. Future runs use the selection through
--projectwithout the override;--lockedchecks that it has not drifted. If the source changes later, try it with--dialect, then runrootform update dialect network-reviewto record the new digest.initnever adopts source drift. If your owner collides with an embedded Dialect,addrequires an explicit--replace; review the loss of that embedded owner's Rules first.
After selection, a source edit changes the compiled content digest. A normal locked run refuses it instead of silently adopting new meaning. Continue testing the edited source with --dialect; when its fixture and analysis are right, run rootform update dialect network-review from the project root and review the lock diff. Commit the updated source, golden, and lock together.
From the project root, copy the selected Dialect into the project so another checkout can use it without the original source directory:
rootform vendor dialects --offlinegit add rootform.lock .rootform/dialects/network-reviewThe vendored copy lives at .rootform/dialects/network-review/. In a clone
that contains the lock and this directory, prepare and analyze offline:
rootform init . --locked --offline --no-inputrootform run plan.json --plan-file plan.tfplan --locked --no-serveSee the rootform vendor dialects reference
for selection requirements and other destinations, and
external content storage for what to commit. For
several repositories, package and publish the Dialect,
then select its reviewed OCI reference in each project.
If the project no longer needs this interpretation, remove its selection:
rootform remove dialects network-reviewrootform.lock updated
remove Dialect network-review 0.1.0 (dialects/network-review)The source directory remains. A later analysis can still show the base Representation for random_pet.service, but no Rule interprets it. Reproduce an analysis offline shows how to prove another environment loaded a reviewed selection.