{"id":"85b9a28a-80a0-4754-b480-e0d6c08e48fb","entityType":"agent","slug":"clawhub-iliaal-compound-eng-terraform","name":"ia-terraform","canonicalUrl":"https://www.xpersona.co/agent/clawhub-iliaal-compound-eng-terraform","canonicalPath":"/agent/clawhub-iliaal-compound-eng-terraform","generatedAt":"2026-10-09T23:41:50.736Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-09T23:34:43.606Z","emptyReason":null},"description":"Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns. Skill: ia-terraform Owner: iliaal Summary: Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns. Tags: latest:5.0.1 Version history: v5.0.1 | 2026-10-03T17:08:05.450Z | user v5.0.1 v5.0.0 | 2026-09-26T23:22:19.785Z | user v5.0.0 v4.5.3 | 2026-09-13T14:43:05.101Z | user v4.5.3 v4.5.2 |","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.9K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s17bcar8wq0xhegs0ny6f57ypd8484bw:compound-eng-terraform","sourceUrl":"https://clawhub.ai/iliaal/compound-eng-terraform","homepage":"https://clawhub.ai/iliaal/skills/compound-eng-terraform","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/iliaal/compound-eng-terraform","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/iliaal/skills/compound-eng-terraform","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":42,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state "},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:34:43.606Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:34:43.606Z","emptyReason":null},"stars":null,"forks":null,"downloads":1884,"packageName":null,"latestVersion":"5.0.1","tractionLabel":"1.9K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:34:43.606Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T23:34:43.606Z","lastCrawledAt":"2026-10-09T23:34:43.606Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T23:34:43.606Z","lastVerifiedAt":null,"highlights":[{"version":"5.0.1","createdAt":"2026-10-03T17:08:05.450Z","changelog":"v5.0.1","fileCount":5,"zipByteSize":9330},{"version":"5.0.0","createdAt":"2026-09-26T23:22:19.785Z","changelog":"v5.0.0","fileCount":5,"zipByteSize":8172},{"version":"4.5.3","createdAt":"2026-09-13T14:43:05.101Z","changelog":"v4.5.3","fileCount":5,"zipByteSize":8519},{"version":"4.5.2","createdAt":"2026-09-08T01:41:13.986Z","changelog":"v4.5.2","fileCount":5,"zipByteSize":8047},{"version":"4.5.0","createdAt":"2026-08-29T22:24:37.939Z","changelog":"v4.5.0","fileCount":4,"zipByteSize":7524},{"version":"4.3.2","createdAt":"2026-07-27T20:53:03.747Z","changelog":"v4.3.2","fileCount":4,"zipByteSize":6957},{"version":"4.2.0","createdAt":"2026-07-07T18:39:57.755Z","changelog":"v4.2.0","fileCount":4,"zipByteSize":6456},{"version":"3.0.5","createdAt":"2026-04-30T00:04:14.037Z","changelog":"v3.0.5","fileCount":4,"zipByteSize":6199}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17bcar8wq0xhegs0ny6f57ypd8484bw:compound-eng-terraform","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T23:41:50.733Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-iliaal-compound-eng-terraform/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-09T23:34:43.606Z","emptyReason":null},"readme":"Skill: ia-terraform\n\nOwner: iliaal\n\nSummary: Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\nTags: latest:5.0.1\n\nVersion history:\n\nv5.0.1 | 2026-10-03T17:08:05.450Z | user\n\nv5.0.1\n\nv5.0.0 | 2026-09-26T23:22:19.785Z | user\n\nv5.0.0\n\nv4.5.3 | 2026-09-13T14:43:05.101Z | user\n\nv4.5.3\n\nv4.5.2 | 2026-09-08T01:41:13.986Z | user\n\nv4.5.2\n\nv4.5.0 | 2026-08-29T22:24:37.939Z | user\n\nv4.5.0\n\nv4.3.2 | 2026-07-27T20:53:03.747Z | user\n\nv4.3.2\n\nv4.2.0 | 2026-07-07T18:39:57.755Z | user\n\nv4.2.0\n\nv3.0.5 | 2026-04-30T00:04:14.037Z | user\n\nv3.0.5\n\nv3.0.4 | 2026-04-27T14:40:09.177Z | user\n\nv3.0.4\n\nv3.0.3 | 2026-04-24T12:35:48.520Z | user\n\nv3.0.3\n\nv3.0.2 | 2026-04-24T11:51:01.087Z | user\n\nv3.0.2\n\nv3.0.1 | 2026-04-24T11:31:40.828Z | user\n\nv3.0.1\n\nv3.0.0 | 2026-04-23T19:29:01.842Z | user\n\nv3.0.0\n\nv2.56.1 | 2026-04-18T13:30:56.365Z | user\n\nv2.56.1\n\nv2.56.0 | 2026-04-14T12:41:04.448Z | user\n\nv2.56.0\n\nv2.55.1 | 2026-04-12T14:31:12.726Z | user\n\nv2.55.1\n\nv2.55.0 | 2026-04-11T01:01:54.631Z | user\n\nv2.55.0\n\nv2.53.2 | 2026-04-08T14:21:46.898Z | user\n\nv2.53.2\n\nv2.53.0 | 2026-04-07T01:56:14.051Z | user\n\nv2.53.0\n\nArchive index:\n\nArchive v5.0.1: 5 files, 9330 bytes\n\nFiles: references/native-test-patterns.md (4224b), skill-card.md (1759b), SKILL.md (8171b), SPEC.md (4387b), _meta.json (141b)\n\nFile v5.0.1:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## Working rules\n\n- Preserve state and resource addresses during refactoring; inspect the plan for unintended replacement.\n- Separate tests with verified local or mocked effects from tests that access real services or create billable infrastructure. Plan mode can still read real data sources; mocked apply can run without infrastructure creation.\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each`: removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9.0\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1.0\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP; check current release status): orchestrates multiple configs as a single deployment unit. Evaluate for multi-environment patterns.\n\n\n## State & Security\n\n- Remote backend with locking: S3 with `use_lockfile = true` (1.10+), Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure. DynamoDB-based S3 locking (`dynamodb_table`) is deprecated and slated for removal; prefer `use_lockfile`. Both may be set at once while migrating an existing table off.\n- OpenTofu-only: `terraform { encryption { key_provider \"pbkdf2\" \"k\" {...}  method \"aes_gcm\" \"m\" { keys = key_provider.pbkdf2.k }  state { method = method.aes_gcm.m }  plan { method = method.aes_gcm.m } } }` encrypts state and plan files client-side (or via `TF_ENCRYPTION`). Roll out with a `fallback { method = method.unencrypted.x }` so existing plaintext state still loads, and never rename a key provider or method without a `fallback` block. OpenTofu also accepts `var.*`/`local.*` in `backend {}` arguments and in module `source`/`version` (resolved at `init`; no state or provider-function references); the same HCL is a hard error in Terraform (\"A backend block cannot refer to named values\").\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default; public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials; use assume_role, OIDC, or secrets managers.\n- Pre-commit: auto-format first (`terraform fmt -recursive` rewrites files), then verify (`terraform validate && tflint && trivy config .`)\n- Use `moved` blocks with `from` and `to` addresses for refactoring resource names/modules without destroy-recreate. Retain historical moves for downstream upgrades; remove only after every affected state has migrated, or as an explicitly breaking module release.\n- `lifecycle { ignore_changes = [attr] }` suppresses **updates only**, and it substitutes the prior state value at plan time, on the *first* plan after the config change, with no \"first apply\" exception. Two consequences reviewers get backwards: (1) on an already-provisioned resource the literal in the config is never written, and `ForceNew` never fires because `ignore_changes` erased the diff before replacement is evaluated, so a change that replaces a committed value with a placeholder scrubs the repository and leaves the remote value live; (2) `ignore_changes` does not apply on create, so any later `-replace`, taint, `state rm` + re-add, or manual deletion re-seeds the placeholder over a value that was set out of band. Keep only the container resource in configuration and provision the value entirely out of band, or state the restore step in the runbook for every replace path.\n\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>`, only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations, which prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs; never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors. Inspect providers, data sources, provisioners, and external commands before selecting test files. Include safe plan tests and fully mocked apply tests in completion checks. Keep real-service or infrastructure tests behind the task's authorization and cost boundary. Pass the root-relative test filename, such as `terraform test -filter=tests/vpc_unit_test.tftest.hcl`, and verify that the intended file completed at least one run; an exit code alone can accept an unknown filter with no tests selected. Use the checked selection recipe in [native-test-patterns.md](./references/native-test-patterns.md).\n\n## Task-specific references\n\nRead the relevant reference before implementing or reviewing the matching behavior:\n\n- For native plan/apply tests, fixture ordering, or CI test selection: [native-test-patterns.md](./references/native-test-patterns.md).\n\nFile v5.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"5.0.1\",\n  \"publishedAt\": 1791047285450\n}\n\nFile v5.0.1:references/native-test-patterns.md\n\n# Native test patterns\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Provider-free unit tests (1.7+) | Native plan or apply tests with mocked providers and no external effects |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` checks planned values; `command = apply` checks resulting state (default). Mocked apply is also a unit-test option.\n- Place `condition` and `error_message` on separate lines inside each `assert` block; multiple assertions are allowed per run.\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider` replaces provider operations for both plan and apply. Computed values are generated during apply by default; use `override_during = plan` when a plan assertion needs them. Mock every provider used by the selected run, including aliases. Inspect provisioners, external commands, and built-in resources separately; mocking one provider does not make the whole test safe.\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state; creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` for verified local/mocked effects; `*_integration_test.tftest.hcl` for real services or infrastructure, regardless of command mode.\n- A `module {}` block inside a `run` accepts local paths and registry modules only, not git or HTTP sources. Repos consuming git-sourced modules must vendor or localize them before they can be tested.\n- After a test file completes, resources are destroyed in **reverse run-block order**. Order dependent runs accordingly (create the bucket before the run that puts objects in it), or the destroy fails and leaves billable resources behind. There is no CLI flag to skip cleanup; inspect a failure with `-verbose`.\n\n**Running them:**\n\n```bash\nterraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=tests/vpc_unit_test.tftest.hcl # root-relative FILE, not a run name\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir\n```\n\nAn unknown filter can emit only a warning and finish with zero tests. Check the selected file and a nonzero passed-run count after a successful command:\n\n```bash\nset -euo pipefail\ntest_file=tests/vpc_unit_test.tftest.hcl\nreport=$(mktemp)\ntrap 'rm -f -- \"$report\"' EXIT\nif terraform test -json \"-filter=$test_file\" >\"$report\"; then\n    :\nelse\n    status=$?\n    cat \"$report\" >&2\n    exit \"$status\"\nfi\njq -e -s --arg file \"$test_file\" '\n  any(.[]; .type == \"test_run\" and .test_run.path == $file\n      and .test_run.progress == \"complete\" and .test_run.status == \"pass\")\n  and any(.[]; .type == \"test_summary\" and .test_summary.status == \"pass\"\n          and .test_summary.passed > 0)\n' \"$report\"\n```\n\nFor this local `main.tf`, a mocked apply can check a computed ID without contacting a provider service:\n\n```hcl\nresource \"terraform_data\" \"item\" {\n  input = \"unit-test\"\n}\n\noutput \"item_id\" {\n  value = terraform_data.item.id\n}\n```\n\nPlace the following test in `tests/vpc_unit_test.tftest.hcl` for the selection recipe above. The built-in provider is mocked; no provisioner or external command runs:\n\n```hcl\nmock_provider \"terraform\" {\n  mock_resource \"terraform_data\" {\n    defaults = {\n      id = \"unit-test-id\"\n    }\n  }\n}\n\nrun \"computed_output\" {\n  command = apply\n\n  assert {\n    condition     = output.item_id == \"unit-test-id\"\n    error_message = \"The module must expose the computed ID.\"\n  }\n}\n```\n\nRun verified local/mocked suites on every PR. Run real-service or infrastructure suites only with the required authorization, credentials, cost budget, and cleanup checks.\n\nFile v5.0.1:skill-card.md\n\n## Description:\n\nProvides Terraform and OpenTofu guidance for configuration, modules, testing, state management, and HCL review.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iliaal](https://clawhub.ai/user/iliaal)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and infrastructure engineers use this skill to write and review Terraform or OpenTofu modules, validate HCL, plan safe state changes, and choose appropriate infrastructure tests.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Infrastructure changes can replace resources or incur costs.\n\nMitigation: Review plans for unintended replacements and require explicit authorization and budget controls before real infrastructure tests or applies.\n\nRisk: State files or hardcoded credentials can expose sensitive information.\n\nMitigation: Keep state and credentials out of version control; use a protected remote backend and managed credentials.\n\n## Reference(s):\n\n- [ClawHub skill listing](https://clawhub.ai/iliaal/skills/compound-eng-terraform)\n- [Native test patterns](references/native-test-patterns.md)\n\n## Skill Output:\n\n**Output Type(s):** [Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with HCL and shell snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Review generated plans and authorize tests that access real services.]\n\n## Skill Version(s):\n\n5.0.1 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v5.0.1:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md`: runtime instructions and reference routing.\n- `references/*.md`: bundled supplementary content (1 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl`: positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh`: regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/`: harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release`; never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v5.0.0: 5 files, 8172 bytes\n\nFiles: references/native-test-patterns.md (2253b), skill-card.md (1476b), SKILL.md (7648b), SPEC.md (4387b), _meta.json (141b)\n\nFile v5.0.0:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## Working rules\n\n- Preserve state and resource addresses during refactoring; inspect the plan for unintended replacement.\n- Separate plan-only checks from apply-mode tests that create real infrastructure and incur cost.\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each`: removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9.0\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1.0\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP; check current release status): orchestrates multiple configs as a single deployment unit. Evaluate for multi-environment patterns.\n\n\n## State & Security\n\n- Remote backend with locking: S3 with `use_lockfile = true` (1.10+), Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure. DynamoDB-based S3 locking (`dynamodb_table`) is deprecated and slated for removal; prefer `use_lockfile`. Both may be set at once while migrating an existing table off.\n- OpenTofu-only: `terraform { encryption { key_provider \"pbkdf2\" \"k\" {...}  method \"aes_gcm\" \"m\" { keys = key_provider.pbkdf2.k }  state { method = method.aes_gcm.m }  plan { method = method.aes_gcm.m } } }` encrypts state and plan files client-side (or via `TF_ENCRYPTION`). Roll out with a `fallback { method = method.unencrypted.x }` so existing plaintext state still loads, and never rename a key provider or method without a `fallback` block. OpenTofu also accepts `var.*`/`local.*` in `backend {}` arguments and in module `source`/`version` (resolved at `init`; no state or provider-function references); the same HCL is a hard error in Terraform (\"A backend block cannot refer to named values\").\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default; public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials; use assume_role, OIDC, or secrets managers.\n- Pre-commit: auto-format first (`terraform fmt -recursive` rewrites files), then verify (`terraform validate && tflint && trivy config .`)\n- Use `moved` blocks with `from` and `to` addresses for refactoring resource names/modules without destroy-recreate. Retain historical moves for downstream upgrades; remove only after every affected state has migrated, or as an explicitly breaking module release.\n- `lifecycle { ignore_changes = [attr] }` suppresses **updates only**, and it substitutes the prior state value at plan time, on the *first* plan after the config change, with no \"first apply\" exception. Two consequences reviewers get backwards: (1) on an already-provisioned resource the literal in the config is never written, and `ForceNew` never fires because `ignore_changes` erased the diff before replacement is evaluated, so a change that replaces a committed value with a placeholder scrubs the repository and leaves the remote value live; (2) `ignore_changes` does not apply on create, so any later `-replace`, taint, `state rm` + re-add, or manual deletion re-seeds the placeholder over a value that was set out of band. Keep only the container resource in configuration and provision the value entirely out of band, or state the restore step in the runbook for every replace path.\n\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>`, only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations, which prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs; never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors. Where plan-mode tests exist, add `terraform test -filter=<unit-test-file>`. Restrict this to plan-mode suites, since apply-mode tests stand up real infrastructure and do not belong in a pre-completion check.\n\n## Task-specific references\n\nRead the relevant reference before implementing or reviewing the matching behavior:\n\n- For native plan/apply tests, fixture ordering, or CI test selection: [native-test-patterns.md](./references/native-test-patterns.md).\n\nFile v5.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"5.0.0\",\n  \"publishedAt\": 1790464939785\n}\n\nFile v5.0.0:references/native-test-patterns.md\n\n# Native test patterns\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }`: multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }`: plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state; creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n- A `module {}` block inside a `run` accepts local paths and registry modules only, not git or HTTP sources. Repos consuming git-sourced modules must vendor or localize them before they can be tested.\n- After a test file completes, resources are destroyed in **reverse run-block order**. Order dependent runs accordingly (create the bucket before the run that puts objects in it), or the destroy fails and leaves billable resources behind. There is no CLI flag to skip cleanup; inspect a failure with `-verbose`.\n\n**Running them:**\n\n```bash\nterraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=vpc_unit_test.tftest.hcl    # one test FILE (not a run-block name)\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir\n```\n\nSplit by cost in CI: plan-mode unit tests on every PR, apply-mode integration tests on merge only.\n\nFile v5.0.0:skill-card.md\n\n## Description:\n\nProvides guidance on Terraform and OpenTofu configuration, modules, testing, state management, and HCL review.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iliaal](https://clawhub.ai/user/iliaal)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and infrastructure engineers use this skill to write and review Terraform or OpenTofu configurations, structure modules, plan tests, and manage state changes.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Suggested apply, refresh, replace, import, or force-unlock commands can change infrastructure or state.\n\nMitigation: Review the plan and target workspace before running infrastructure-changing commands.\n\n## Reference(s):\n\n- [ClawHub skill listing](https://clawhub.ai/iliaal/skills/compound-eng-terraform)\n- [Native test patterns](references/native-test-patterns.md)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Code, Shell commands, Configuration instructions]\n\n**Output Format:** [Markdown with HCL and shell examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [None]\n\n## Skill Version(s):\n\n5.0.0 (source: ClawHub release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v5.0.0:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md`: runtime instructions and reference routing.\n- `references/*.md`: bundled supplementary content (1 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl`: positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh`: regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/`: harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release`; never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v4.5.3: 5 files, 8519 bytes\n\nFiles: references/native-test-patterns.md (2263b), skill-card.md (2267b), SKILL.md (7669b), SPEC.md (4399b), _meta.json (141b)\n\nFile v4.5.3:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## Working rules\n\n- Preserve state and resource addresses during refactoring; inspect the plan for unintended replacement.\n- Separate plan-only checks from apply-mode tests that create real infrastructure and incur cost.\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9.0\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1.0\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP -- check current release status): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n\n## State & Security\n\n- Remote backend with locking: S3 with `use_lockfile = true` (1.10+), Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure. DynamoDB-based S3 locking (`dynamodb_table`) is deprecated and slated for removal -- prefer `use_lockfile`; both may be set at once while migrating an existing table off.\n- OpenTofu-only: `terraform { encryption { key_provider \"pbkdf2\" \"k\" {...}  method \"aes_gcm\" \"m\" { keys = key_provider.pbkdf2.k }  state { method = method.aes_gcm.m }  plan { method = method.aes_gcm.m } } }` encrypts state and plan files client-side (or via `TF_ENCRYPTION`). Roll out with a `fallback { method = method.unencrypted.x }` so existing plaintext state still loads, and never rename a key provider or method without a `fallback` block. OpenTofu also accepts `var.*`/`local.*` in `backend {}` arguments and in module `source`/`version` (resolved at `init`; no state or provider-function references); the same HCL is a hard error in Terraform (\"A backend block cannot refer to named values\").\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: auto-format first (`terraform fmt -recursive` -- rewrites files), then verify (`terraform validate && tflint && trivy config .`)\n- Use `moved` blocks with `from` and `to` addresses for refactoring resource names/modules without destroy-recreate. Retain historical moves for downstream upgrades; remove only after every affected state has migrated, or as an explicitly breaking module release.\n- `lifecycle { ignore_changes = [attr] }` suppresses **updates only**, and it substitutes the prior state value at plan time -- on the *first* plan after the config change, with no \"first apply\" exception. Two consequences reviewers get backwards: (1) on an already-provisioned resource the literal in the config is never written, and `ForceNew` never fires because `ignore_changes` erased the diff before replacement is evaluated -- so a change that replaces a committed value with a placeholder scrubs the repository and leaves the remote value live; (2) `ignore_changes` does not apply on create, so any later `-replace`, taint, `state rm` + re-add, or manual deletion re-seeds the placeholder over a value that was set out of band. Keep only the container resource in configuration and provision the value entirely out of band, or state the restore step in the runbook for every replace path.\n\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors. Where plan-mode tests exist, add `terraform test -filter=<unit-test-file>` -- restrict this to plan-mode suites, since apply-mode tests stand up real infrastructure and do not belong in a pre-completion check.\n\n## Task-specific references\n\nRead the relevant reference before implementing or reviewing the matching behavior:\n\n- For native plan/apply tests, fixture ordering, or CI test selection: [native-test-patterns.md](./references/native-test-patterns.md).\n\nFile v4.5.3:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"4.5.3\",\n  \"publishedAt\": 1789310585101\n}\n\nFile v4.5.3:references/native-test-patterns.md\n\n# Native test patterns\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n- A `module {}` block inside a `run` accepts local paths and registry modules only -- not git or HTTP sources. Repos consuming git-sourced modules must vendor or localize them before they can be tested.\n- After a test file completes, resources are destroyed in **reverse run-block order**. Order dependent runs accordingly (create the bucket before the run that puts objects in it), or the destroy fails and leaves billable resources behind. There is no CLI flag to skip cleanup -- inspect a failure with `-verbose`.\n\n**Running them:**\n\n```bash\nterraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=vpc_unit_test.tftest.hcl    # one test FILE (not a run-block name)\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir\n```\n\nSplit by cost in CI: plan-mode unit tests on every PR, apply-mode integration tests on merge only.\n\nFile v4.5.3:skill-card.md\n\n## Description:\n\nHelps agents work on Terraform and OpenTofu configuration, modules, testing, state management, and HCL review.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iliaal](https://clawhub.ai/user/iliaal)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and infrastructure engineers use this skill to produce, review, test, and troubleshoot Terraform or OpenTofu modules, state changes, HCL, tfvars, and IaC workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Terraform apply, replace, import, force-unlock, and refresh-only operations can affect live infrastructure, state, availability, or cloud cost.\n\nMitigation: Review the Terraform plan and confirm the target workspace, account, and operation intent before allowing those commands to proceed.\n\nRisk: Apply-mode tests and real infrastructure validation can create billable resources.\n\nMitigation: Keep plan-mode tests in routine validation and reserve apply-mode integration tests for controlled environments with explicit cost and cleanup expectations.\n\nRisk: Terraform state and plan files may contain sensitive infrastructure data.\n\nMitigation: Use remote state with locking and encryption, avoid committing state or plan files, and keep credentials in role-based or secret-manager workflows.\n\n## Reference(s):\n\n- [Native test patterns](artifact/references/native-test-patterns.md)\n- [ia-terraform ClawHub page](https://clawhub.ai/iliaal/skills/compound-eng-terraform)\n- [iliaal ClawHub profile](https://clawhub.ai/user/iliaal)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Code, Shell commands, Configuration instructions, Markdown]\n\n**Output Format:** [Markdown with HCL and bash code blocks]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Terraform/OpenTofu file structure guidance, review findings, command sequences, and test recommendations.]\n\n## Skill Version(s):\n\n4.5.3 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v4.5.3:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md` -- runtime instructions and reference routing.\n- `references/*.md` -- bundled supplementary content (0 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl` -- positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh` -- regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/` -- harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release` -- never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v4.5.2: 5 files, 8047 bytes\n\nFiles: references/native-test-patterns.md (2263b), skill-card.md (1910b), SKILL.md (6966b), SPEC.md (4399b), _meta.json (141b)\n\nFile v4.5.2:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## Working rules\n\n- Preserve state and resource addresses during refactoring; inspect the plan for unintended replacement.\n- Separate plan-only checks from apply-mode tests that create real infrastructure and incur cost.\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9.0\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1.0\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP -- check current release status): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n\n## State & Security\n\n- Remote backend with locking: S3 with `use_lockfile = true` (1.10+), Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure. DynamoDB-based S3 locking (`dynamodb_table`) is deprecated and slated for removal -- prefer `use_lockfile`; both may be set at once while migrating an existing table off.\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: auto-format first (`terraform fmt -recursive` -- rewrites files), then verify (`terraform validate && tflint && trivy config .`)\n- Use `moved` blocks with `from` and `to` addresses for refactoring resource names/modules without destroy-recreate. Retain historical moves for downstream upgrades; remove only after every affected state has migrated, or as an explicitly breaking module release.\n- `lifecycle { ignore_changes = [attr] }` suppresses **updates only**, and it substitutes the prior state value at plan time -- on the *first* plan after the config change, with no \"first apply\" exception. Two consequences reviewers get backwards: (1) on an already-provisioned resource the literal in the config is never written, and `ForceNew` never fires because `ignore_changes` erased the diff before replacement is evaluated -- so a change that replaces a committed value with a placeholder scrubs the repository and leaves the remote value live; (2) `ignore_changes` does not apply on create, so any later `-replace`, taint, `state rm` + re-add, or manual deletion re-seeds the placeholder over a value that was set out of band. Keep only the container resource in configuration and provision the value entirely out of band, or state the restore step in the runbook for every replace path.\n\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors. Where plan-mode tests exist, add `terraform test -filter=<unit-test-file>` -- restrict this to plan-mode suites, since apply-mode tests stand up real infrastructure and do not belong in a pre-completion check.\n\n## Task-specific references\n\nRead the relevant reference before implementing or reviewing the matching behavior:\n\n- For native plan/apply tests, fixture ordering, or CI test selection: [native-test-patterns.md](./references/native-test-patterns.md).\n\nFile v4.5.2:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"4.5.2\",\n  \"publishedAt\": 1788831673986\n}\n\nFile v4.5.2:references/native-test-patterns.md\n\n# Native test patterns\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n- A `module {}` block inside a `run` accepts local paths and registry modules only -- not git or HTTP sources. Repos consuming git-sourced modules must vendor or localize them before they can be tested.\n- After a test file completes, resources are destroyed in **reverse run-block order**. Order dependent runs accordingly (create the bucket before the run that puts objects in it), or the destroy fails and leaves billable resources behind. There is no CLI flag to skip cleanup -- inspect a failure with `-verbose`.\n\n**Running them:**\n\n```bash\nterraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=vpc_unit_test.tftest.hcl    # one test FILE (not a run-block name)\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir\n```\n\nSplit by cost in CI: plan-mode unit tests on every PR, apply-mode integration tests on merge only.\n\nFile v4.5.2:skill-card.md\n\n## Description:\n\nGuides agents on Terraform and OpenTofu configuration, modules, testing, state management, and HCL review for IaC tasks.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iliaal](https://clawhub.ai/user/iliaal)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and infrastructure engineers use this skill to author, review, test, and troubleshoot Terraform/OpenTofu modules and configurations while preserving state and controlling apply-mode risk.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Apply-mode Terraform tests and state operations can create, modify, or replace real infrastructure and may incur cost.\n\nMitigation: Review Terraform plans, avoid apply-mode tests unless intended, and require explicit confirmation before state-changing commands.\n\nRisk: Formatting and validation workflows may rewrite local Terraform files or depend on local tool availability.\n\nMitigation: Run formatting deliberately, inspect diffs after rewrites, and treat missing local tools as setup blockers rather than bypassing validation.\n\n## Reference(s):\n\n- [Native test patterns](references/native-test-patterns.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline HCL and shell command examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May propose Terraform/OpenTofu validation, formatting, testing, and state-management commands; review commands before execution.]\n\n## Skill Version(s):\n\n4.5.2 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v4.5.2:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md` -- runtime instructions and reference routing.\n- `references/*.md` -- bundled supplementary content (0 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl` -- positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh` -- regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/` -- harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release` -- never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v4.5.0: 4 files, 7524 bytes\n\nFiles: skill-card.md (2144b), SKILL.md (8583b), SPEC.md (4399b), _meta.json (141b)\n\nFile v4.5.0:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n- A `module {}` block inside a `run` accepts local paths and registry modules only -- not git or HTTP sources. Repos consuming git-sourced modules must vendor or localize them before they can be tested.\n- After a test file completes, resources are destroyed in **reverse run-block order**. Order dependent runs accordingly (create the bucket before the run that puts objects in it), or the destroy fails and leaves billable resources behind. There is no CLI flag to skip cleanup -- inspect a failure with `-verbose`.\n\n**Running them:**\n\n```bash\nterraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=vpc_unit_test.tftest.hcl    # one test FILE (not a run-block name)\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir\n```\n\nSplit by cost in CI: plan-mode unit tests on every PR, apply-mode integration tests on merge only.\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP -- check current release status): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n## State & Security\n\n- Remote backend with locking: S3 with `use_lockfile = true` (1.10+), Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure. DynamoDB-based S3 locking (`dynamodb_table`) is deprecated and slated for removal -- prefer `use_lockfile`; both may be set at once while migrating an existing table off.\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: auto-format first (`terraform fmt -recursive` -- rewrites files), then verify (`terraform validate && tflint && trivy config .`)\n- `moved { from = old; to = new }` for refactoring resource names/modules without destroy-recreate. Remove block after apply.\n- `lifecycle { ignore_changes = [attr] }` suppresses **updates only**, and it substitutes the prior state value at plan time -- on the *first* plan after the config change, with no \"first apply\" exception. Two consequences reviewers get backwards: (1) on an already-provisioned resource the literal in the config is never written, and `ForceNew` never fires because `ignore_changes` erased the diff before replacement is evaluated -- so a change that replaces a committed value with a placeholder scrubs the repository and leaves the remote value live; (2) `ignore_changes` does not apply on create, so any later `-replace`, taint, `state rm` + re-add, or manual deletion re-seeds the placeholder over a value that was set out of band. Keep only the container resource in configuration and provision the value entirely out of band, or state the restore step in the runbook for every replace path.\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors. Where plan-mode tests exist, add `terraform test -filter=<unit-test-file>` -- restrict this to plan-mode suites, since apply-mode tests stand up real infrastructure and do not belong in a pre-completion check.\n\nFile v4.5.0:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"4.5.0\",\n  \"publishedAt\": 1788042277939\n}\n\nFile v4.5.0:skill-card.md\n\n## Description:\n\nTerraform and OpenTofu configuration, modules, testing, state management, and HCL review for agents working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iliaal](https://clawhub.ai/user/iliaal)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and infrastructure engineers use this skill for Terraform/OpenTofu module authoring, HCL review, testing, state-management guidance, and safe IaC workflow checks.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Generated Terraform or OpenTofu changes can alter live infrastructure, create cost, or destroy resources if applied without review.\n\nMitigation: Review generated HCL, plans, and module changes before applying them, and require explicit user confirmation before any real apply operation.\n\nRisk: State operations such as import, force-unlock, refresh-only apply, or replace can affect existing infrastructure state.\n\nMitigation: Treat state-changing commands as user-directed work, confirm the target workspace and resource address, and verify no competing operation is running before lock or state changes.\n\nRisk: Terraform state, plan files, and provider configuration can contain sensitive values.\n\nMitigation: Keep state remote and encrypted, do not commit state or plan files, and use role assumption, OIDC, or secrets managers rather than hardcoded credentials.\n\n## Reference(s):\n\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline HCL and bash code blocks]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Guidance should be reviewed before applying infrastructure changes.]\n\n## Skill Version(s):\n\n4.5.0 (source: release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v4.5.0:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md` -- runtime instructions and reference routing.\n- `references/*.md` -- bundled supplementary content (0 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl` -- positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh` -- regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/` -- harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release` -- never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v4.3.2: 4 files, 6957 bytes\n\nFiles: skill-card.md (1874b), SKILL.md (7686b), SPEC.md (4399b), _meta.json (141b)\n\nFile v4.3.2:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n- A `module {}` block inside a `run` accepts local paths and registry modules only -- not git or HTTP sources. Repos consuming git-sourced modules must vendor or localize them before they can be tested.\n- After a test file completes, resources are destroyed in **reverse run-block order**. Order dependent runs accordingly (create the bucket before the run that puts objects in it), or the destroy fails and leaves billable resources behind. There is no CLI flag to skip cleanup -- inspect a failure with `-verbose`.\n\n**Running them:**\n\n```bash\nterraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=vpc_unit_test.tftest.hcl    # one test FILE (not a run-block name)\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir\n```\n\nSplit by cost in CI: plan-mode unit tests on every PR, apply-mode integration tests on merge only.\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP -- check current release status): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n## State & Security\n\n- Remote backend with locking: S3 with `use_lockfile = true` (1.10+), Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure. DynamoDB-based S3 locking (`dynamodb_table`) is deprecated and slated for removal -- prefer `use_lockfile`; both may be set at once while migrating an existing table off.\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: auto-format first (`terraform fmt -recursive` -- rewrites files), then verify (`terraform validate && tflint && trivy config .`)\n- `moved { from = old; to = new }` for refactoring resource names/modules without destroy-recreate. Remove block after apply.\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors. Where plan-mode tests exist, add `terraform test -filter=<unit-test-file>` -- restrict this to plan-mode suites, since apply-mode tests stand up real infrastructure and do not belong in a pre-completion check.\n\nFile v4.3.2:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"4.3.2\",\n  \"publishedAt\": 1785185583747\n}\n\nFile v4.3.2:skill-card.md\n\n## Description: <br>\nTerraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[iliaal](https://clawhub.ai/user/iliaal) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and infrastructure engineers use this skill for Terraform and OpenTofu module design, HCL review, testing guidance, state management, and infrastructure-as-code troubleshooting. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Suggested Terraform or OpenTofu commands can affect real infrastructure when deliberately run. <br>\nMitigation: Review generated plans and avoid apply, state, import, refresh-only, force-unlock, or replacement operations unless the operator intends those infrastructure changes. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/iliaal/skills/compound-eng-terraform) <br>\n- [SKILL.md](artifact/SKILL.md) <br>\n- [SPEC.md](artifact/SPEC.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration] <br>\n**Output Format:** [Markdown with inline HCL and shell command examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Guidance is documentation-only; users decide whether to run any suggested Terraform or OpenTofu commands.] <br>\n\n## Skill Version(s): <br>\n4.3.2 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v4.3.2:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md` -- runtime instructions and reference routing.\n- `references/*.md` -- bundled supplementary content (0 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl` -- positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh` -- regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/` -- harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release` -- never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v4.2.0: 4 files, 6456 bytes\n\nFiles: skill-card.md (2043b), SKILL.md (6296b), SPEC.md (4399b), _meta.json (141b)\n\nFile v4.2.0:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP -- check current release status): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n## State & Security\n\n- Remote backend with locking: S3+DynamoDB, Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure.\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: auto-format first (`terraform fmt -recursive` -- rewrites files), then verify (`terraform validate && tflint && trivy config .`)\n- `moved { from = old; to = new }` for refactoring resource names/modules without destroy-recreate. Remove block after apply.\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors.\n\nFile v4.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"4.2.0\",\n  \"publishedAt\": 1783449597755\n}\n\nFile v4.2.0:skill-card.md\n\n## Description: <br>\nTerraform and OpenTofu configuration, modules, testing, state management, and HCL review. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[iliaal](https://clawhub.ai/user/iliaal) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and infrastructure engineers use this skill to write, review, test, troubleshoot, and maintain Terraform or OpenTofu modules, HCL, tfvars, tftest files, and state-management workflows. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Terraform or OpenTofu recommendations can affect infrastructure, state, access controls, or cloud costs when applied by an agent or operator. <br>\nMitigation: Review generated configuration and plans before apply, use least-privilege credentials, keep remote state encrypted and locked, and run validation and scanning commands such as terraform fmt, terraform validate, tflint, trivy, or checkov. <br>\nRisk: The release security guidance notes that use of operational workflows may involve configured API tokens, admin CLIs, or local notes. <br>\nMitigation: Install only when the publisher is trusted for the intended workflows and use least-privilege tokens for any connected services. <br>\n\n\n## Reference(s): <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown with HCL and shell command examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Produces agent guidance for Terraform and OpenTofu workflows; does not include executable automation in the artifact.] <br>\n\n## Skill Version(s): <br>\n4.2.0 (source: release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v4.2.0:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md` -- runtime instructions and reference routing.\n- `references/*.md` -- bundled supplementary content (0 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl` -- positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh` -- regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/` -- harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release` -- never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v3.0.5: 4 files, 6199 bytes\n\nFiles: skill-card.md (1563b), SKILL.md (6211b), SPEC.md (4432b), _meta.json (141b)\n\nFile v3.0.5:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP, preview): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n## State & Security\n\n- Remote backend with locking: S3+DynamoDB, Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure.\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: `terraform fmt -recursive && terraform validate && trivy config .`\n- `moved { from = old; to = new }` for refactoring resource names/modules without destroy-recreate. Remove block after apply.\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors.\n\nFile v3.0.5:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"3.0.5\",\n  \"publishedAt\": 1777507454037\n}\n\nFile v3.0.5:skill-card.md\n\n## Description: <br>\nTerraform and OpenTofu configuration, modules, testing, state management, and HCL review for Terraform, OpenTofu, HCL, tfvars, tftest, state migration, and IaC patterns. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[iliaal](https://clawhub.ai/user/iliaal) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and infrastructure engineers use this skill to write, review, test, troubleshoot, and maintain Terraform or OpenTofu infrastructure-as-code. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Terraform or OpenTofu commands may affect real cloud resources when run with active credentials. <br>\nMitigation: Review Terraform plans before applying changes and run validation or configuration scans before deployment. <br>\n\n\n## Reference(s): <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown with HCL and shell command examples] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [No structured machine-readable output contract is specified.] <br>\n\n## Skill Version(s): <br>\n3.0.5 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v3.0.5:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/compound-engineering/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md` -- runtime instructions and reference routing.\n- `references/*.md` -- bundled supplementary content (0 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl` -- positive and negative trigger phrasings under regression test.\n- `plugins/compound-engineering/hooks/skill-patterns.sh` -- regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/` -- harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/compound-engineering/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release` -- never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v3.0.4: 3 files, 5294 bytes\n\nFiles: SKILL.md (6211b), SPEC.md (4432b), _meta.json (141b)\n\nFile v3.0.4:SKILL.md\n\n---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP, preview): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n## State & Security\n\n- Remote backend with locking: S3+DynamoDB, Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure.\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: `terraform fmt -recursive && terraform validate && trivy config .`\n- `moved { from = old; to = new }` for refactoring resource names/modules without destroy-recreate. Remove block after apply.\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors.\n\nFile v3.0.4:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"3.0.4\",\n  \"publishedAt\": 1777300809177\n}\n\nFile v3.0.4:SPEC.md\n\n# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/compound-engineering/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md` -- runtime instructions and reference routing.\n- `references/*.md` -- bundled supplementary content (0 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl` -- positive and negative trigger phrasings under regression test.\n- `plugins/compound-engineering/hooks/skill-patterns.sh` -- regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/` -- harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/compound-engineering/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distillery/scripts/distiller.py dspy-eval ia-terraform\npython3 distillery/scripts/distiller.py diagnose-negatives ia-terraform\n```\n\nAcceptance gates:\n- `validate-plugin --component ia-terraform` returns 0 HIGH findings.\n- `test-triggers --skill ia-terraform` returns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.\n- For dspy-eval, the composite score does not regress against the most recent saved baseline (see `distillery/.eval-data/ia-terraform/history.json`).\n\n## Known Limitations\n\n<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives\n     surfaces a recurring failure pattern, document it here so future maintainers\n     understand the trade-off the current implementation accepts. -->\n\n## Maintenance Notes\n\n- Update `SKILL.md` when the runtime workflow, branch conditions, or output contract changes.\n- Update this `SPEC.md` when intent, scope, evidence model, evaluation gates, or maintenance expectations change.\n- Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).\n- Update the hook regex in `skill-patterns.sh` whenever fixture positives expose a missed phrasing; verify F1 = 1.0 with `eval-triggers` before committing.\n- Run the full release pipeline via `/release` -- never bump versions or update CHANGELOG.md from a per-skill edit.\n\nArchive v3.0.3: 2 files, 3234 bytes\n\nFiles: SKILL.md (6195b), _meta.json (141b)\n\nFile v3.0.3:SKILL.md\n\n---\nname: ia-terraform\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each` -- removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Cost-free unit tests (1.7+) | Native tests + `mock_provider` |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` for fast unit tests; `command = apply` for integration (default)\n- `assert { condition = expr; error_message = \"...\" }` -- multiple per run block\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider \"aws\" { mock_resource \"...\" { defaults = { ... } } }` -- plan-mode only, no credentials, fast CI\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state -- creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` (plan mode) vs `*_integration_test.tftest.hcl` (apply mode)\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allow patch | `version = \"~> 5.1\"` |\n\nKey modern features: `moved` blocks (1.1+), `optional()` with defaults (1.3+), native testing (1.6+), mock providers (1.7+), cross-variable validation (1.9+), write-only arguments (1.11+).\nStacks (HCP, preview): orchestrates multiple configs as a single deployment unit -- evaluate for multi-environment patterns.\n\n## State & Security\n\n- Remote backend with locking: S3+DynamoDB, Azure Blob, GCS, or Terraform Cloud. Never local state for shared infrastructure.\n- Encrypt state at rest. Never commit `.tfstate`, `.terraform/`, or `*.tfplan`. Always commit `.terraform.lock.hcl`.\n- `default_tags` on provider for consistent resource tagging.\n- Encryption at rest on all storage. Private networking by default -- public access is opt-in.\n- Least-privilege security groups. No `0.0.0.0/0` ingress without explicit justification.\n- Never hardcode credentials -- use assume_role, OIDC, or secrets managers.\n- Pre-commit: `terraform fmt -recursive && terraform validate && trivy config .`\n- `moved { from = old; to = new }` for refactoring resource names/modules without destroy-recreate. Remove block after apply.\n\n## Troubleshooting\n\n- State lock stuck: `terraform force-unlock <ID>` -- only after confirming no other operation running\n- Resource drift: `terraform plan -refresh-only` to detect, `terraform apply -refresh-only` to accept\n- Replace tainted: `terraform apply -replace=ADDR` (not deprecated `terraform taint`)\n- Import existing: `import` blocks (1.5+) for declarative import, or `terraform import ADDR ID`\n\n## Dependency Management\n\nUse `locals` with `try()` to control deletion ordering without explicit `depends_on`:\n\n```hcl\nlocals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}\n```\n\nThis forces Terraform to destroy subnets before CIDR associations -- prevents deletion errors.\n\n- `cidrsubnet(var.vpc_cidr, 8, count.index)` for calculated subnet CIDRs -- never hardcode subnets\n- Multi-region: `provider \"aws\" { alias = \"eu_west_1\" }` + `providers = { aws = aws.eu_west_1 }` in module blocks\n\n## Verify\n\nRun before declaring done:\n\n```bash\nterraform fmt -check && terraform validate && tflint && trivy config .\n```\n\nAll commands must pass with zero errors.\n\nFile v3.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"3.0.3\",\n  \"publishedAt\": 1777034148520\n}","readmeExcerpt":"Skill: ia-terraform Owner: iliaal Summary: Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns. Tags: latest:5.0.1 Version history: v5.0.1 | 2026-10-03T17:08:05.450Z | user v5.0.1 v5.0.0 | 2026-09-26T23:22:19.785Z | user v5.0.0 v4.5.3 | 2026-09-13T14:43:05.101Z | user v4.5.3 v4.5.2 | ","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"module-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl"},{"language":"hcl","snippet":"locals {\n  vpc_id = try(aws_vpc_ipv4_cidr_block_association.this[0].vpc_id, aws_vpc.this.id, \"\")\n}"},{"language":"bash","snippet":"terraform fmt -check && terraform validate && tflint && trivy config ."},{"language":"bash","snippet":"terraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=tests/vpc_unit_test.tftest.hcl # root-relative FILE, not a run name\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir"},{"language":"bash","snippet":"set -euo pipefail\ntest_file=tests/vpc_unit_test.tftest.hcl\nreport=$(mktemp)\ntrap 'rm -f -- \"$report\"' EXIT\nif terraform test -json \"-filter=$test_file\" >\"$report\"; then\n    :\nelse\n    status=$?\n    cat \"$report\" >&2\n    exit \"$status\"\nfi\njq -e -s --arg file \"$test_file\" '\n  any(.[]; .type == \"test_run\" and .test_run.path == $file\n      and .test_run.progress == \"complete\" and .test_run.status == \"pass\")\n  and any(.[]; .type == \"test_summary\" and .test_summary.status == \"pass\"\n          and .test_summary.passed > 0)\n' \"$report\""},{"language":"hcl","snippet":"resource \"terraform_data\" \"item\" {\n  input = \"unit-test\"\n}\n\noutput \"item_id\" {\n  value = terraform_data.item.id\n}"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: ia-terraform\nclass: language\ndescription: >-\n  Terraform and OpenTofu configuration, modules, testing, state management, and\n  HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest,\n  state migration, or IaC patterns.\npaths: \"**/*.tf,**/*.tfvars\"\n---\n\n# Terraform & OpenTofu\n\n## Working rules\n\n- Preserve state and resource addresses during refactoring; inspect the plan for unintended replacement.\n- Separate tests with verified local or mocked effects from tests that access real services or create billable infrastructure. Plan mode can still read real data sources; mocked apply can run without infrastructure creation.\n\n## File Organization & Naming\n\n| File | Purpose |\n|------|---------|\n| `terraform.tf` | Terraform + provider version requirements |\n| `providers.tf` | Provider configurations |\n| `main.tf` | Primary resources and data sources |\n| `variables.tf` | Input variables (alphabetical) |\n| `outputs.tf` | Output values (alphabetical) |\n| `locals.tf` | Local values |\n\n- Lowercase with underscores: `web_api`, not `webAPI` or `web-api`\n- Descriptive nouns excluding resource type: `aws_instance.web_api` not `aws_instance.web_api_instance`\n- Singular, not plural\n- `this` for singleton resources (one of that type per module)\n- Contextual variable prefixes: `vpc_cidr_block` not `cidr`\n\n\n## Block Ordering\n\n**Resources:** `count`/`for_each` (blank line after) → arguments → nested blocks → `tags` → `depends_on` → `lifecycle` (last)\n\n**Variables:** `description` → `type` → `default` → `validation` → `nullable`\n\nEvery variable needs `type` + `description`. Every output needs `description`. Mark secrets `sensitive = true`.\n\n\n## Module Structure\n\n| Type | Scope | Example |\n|------|-------|---------|\n| Resource Module | Single logical group | VPC + subnets, SG + rules |\n| Infrastructure Module | Collection of resource modules | Networking + compute for one region |\n| Composition | Complete infrastructure | Spans regions/accounts |\n\n```\nmodule-name/\n├── main.tf, variables.tf, outputs.tf, versions.tf\n├── examples/\n│   ├── minimal/\n│   └── complete/\n└── tests/\n    └── defaults.tftest.hcl\n```\n\nKeep modules small (single responsibility). `examples/` double as documentation and integration test fixtures. Semantic versioning for all published modules.\n\n\n## count vs for_each\n\n| Scenario | Use |\n|----------|-----|\n| Boolean toggle (create or skip) | `count = condition ? 1 : 0` |\n| Named/keyed items that may reorder | `for_each = toset(list)` or `map` |\n| Fixed identical replicas | `count = N` |\n\nDefault to `for_each`: removing a middle item from a `count` list recreates all subsequent resources. Use `count` only for boolean conditionals or truly identical replicas.\n\n\n## Version Pinning\n\n| Component | Strategy | Example |\n|-----------|----------|---------|\n| Terraform | Pin minor | `required_version = \"~> 1.9.0\"` |\n| Providers | Pin major | `version = \"~> 5.0\"` |\n| Modules (prod) | Pin exact | `version = \"5.1.2\"` |\n| Modules (dev) | Allo"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn715jrbbh71q9zncr0bqdkr8n848q1a\",\n  \"slug\": \"compound-eng-terraform\",\n  \"version\": \"5.0.1\",\n  \"publishedAt\": 1791047285450\n}"},{"path":"references/native-test-patterns.md","content":"# Native test patterns\n\n## Testing\n\n| Situation | Approach |\n|-----------|----------|\n| Quick validation | `terraform fmt -check && terraform validate` |\n| Pre-commit | + `tflint` + `trivy config .` / `checkov -d .` |\n| Logic validation (1.6+) | Native `terraform test` with `command = plan` |\n| Provider-free unit tests (1.7+) | Native plan or apply tests with mocked providers and no external effects |\n| Real infra validation | Native tests with `command = apply`, or Terratest (Go) |\n\n**Native test essentials** (`.tftest.hcl` in `tests/`):\n- `command = plan` checks planned values; `command = apply` checks resulting state (default). Mocked apply is also a unit-test option.\n- Place `condition` and `error_message` on separate lines inside each `assert` block; multiple assertions are allowed per run.\n- `expect_failures = [var.name]` for negative testing (validate rejection of bad input)\n- `mock_provider` replaces provider operations for both plan and apply. Computed values are generated during apply by default; use `override_during = plan` when a plan assertion needs them. Mock every provider used by the selected run, including aliases. Inspect provisioners, external commands, and built-in resources separately; mocking one provider does not make the whole test safe.\n- `variables {}` at file level (all runs) or within a `run` block (override)\n- Reference prior run outputs: `run.setup.vpc_id`\n- `parallel = true` on independent runs with separate state; creates sync point at next sequential run\n- `state_key = \"name\"` required for `parallel = true` runs with independent state\n- File naming: `*_unit_test.tftest.hcl` for verified local/mocked effects; `*_integration_test.tftest.hcl` for real services or infrastructure, regardless of command mode.\n- A `module {}` block inside a `run` accepts local paths and registry modules only, not git or HTTP sources. Repos consuming git-sourced modules must vendor or localize them before they can be tested.\n- After a test file completes, resources are destroyed in **reverse run-block order**. Order dependent runs accordingly (create the bucket before the run that puts objects in it), or the destroy fails and leaves billable resources behind. There is no CLI flag to skip cleanup; inspect a failure with `-verbose`.\n\n**Running them:**\n\n```bash\nterraform test                                     # all *.tftest.hcl under tests/\nterraform test -filter=tests/vpc_unit_test.tftest.hcl # root-relative FILE, not a run name\nterraform test -verbose                            # show the plan/apply per run block\nterraform test -test-directory=path                # non-default test dir\n```\n\nAn unknown filter can emit only a warning and finish with zero tests. Check the selected file and a nonzero passed-run count after a successful command:\n\n```bash\nset -euo pipefail\ntest_file=tests/vpc_unit_test.tftest.hcl\nreport=$(mktemp)\ntrap 'rm -f -- \"$report\"' EXIT\nif terraform test -json \"-filter=$test_file\" >\"$report\"; then\n    :\nelse\n    status="},{"path":"skill-card.md","content":"## Description:\n\nProvides Terraform and OpenTofu guidance for configuration, modules, testing, state management, and HCL review.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[iliaal](https://clawhub.ai/user/iliaal)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and infrastructure engineers use this skill to write and review Terraform or OpenTofu modules, validate HCL, plan safe state changes, and choose appropriate infrastructure tests.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Infrastructure changes can replace resources or incur costs.\n\nMitigation: Review plans for unintended replacements and require explicit authorization and budget controls before real infrastructure tests or applies.\n\nRisk: State files or hardcoded credentials can expose sensitive information.\n\nMitigation: Keep state and credentials out of version control; use a protected remote backend and managed credentials.\n\n## Reference(s):\n\n- [ClawHub skill listing](https://clawhub.ai/iliaal/skills/compound-eng-terraform)\n- [Native test patterns](references/native-test-patterns.md)\n\n## Skill Output:\n\n**Output Type(s):** [Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with HCL and shell snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Review generated plans and authorize tests that access real services.]\n\n## Skill Version(s):\n\n5.0.1 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."},{"path":"SPEC.md","content":"# ia-terraform Specification\n\n## Intent\n\n`ia-terraform` is a `language`-class skill (stack-specific patterns and idioms). Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns.\n\n## Scope\n\nIn scope:\n- Behaviors described in `SKILL.md` and routed via the should_trigger phrasings in `distillery/tests/fixtures/triggers/ia-terraform.jsonl`.\n- Updates to runtime behavior, structure, trigger precision, references, and validation.\n\nOut of scope:\n- Acting as the runtime instructions themselves (those live in `SKILL.md`).\n- Trigger phrasings already covered by adjacent `ia-*` skills (`validate-plugin` flags >70% description overlap as DUPLICATE_TRIGGER).\n- <!-- to fill in: domain-specific exclusions when the skill drifts -->\n\n## Trigger Context\n\n- Class: `language`\n- Hook regex: `plugins/whetstone/hooks/skill-patterns.sh` -> `SKILL_PATTERNS[ia-terraform]`\n- Common requests (from fixture should_trigger):\n  - \"write a terraform module for the VPC and subnets\"\n  - \"review the infrastructure as code for the staging environment\"\n  - \"write a Terraform module for the VPC\"\n- Should not trigger for (from fixture should_not_trigger):\n  - \"implement the shopping cart feature in React\"\n  - \"add PHPUnit tests for the order service\"\n  - \"write a Pulumi program for the same setup\"\n\n## Source And Evidence Model\n\nAuthoritative sources:\n\n- `SKILL.md`: runtime instructions and reference routing.\n- `references/*.md`: bundled supplementary content (1 file(s)).\n- `distillery/tests/fixtures/triggers/ia-terraform.jsonl`: positive and negative trigger phrasings under regression test.\n- `plugins/whetstone/hooks/skill-patterns.sh`: regex pattern that fires this skill.\n- `distillery/.eval-data/ia-terraform/`: harvested session examples (when present).\n\nData that must not be stored in this skill or its references:\n\n- Secrets, credentials, tokens.\n- Machine-specific filesystem paths (`/home/...`, `/Users/...`, `~/ai/...`). The validator (`MACHINE_PATH_LEAK`) flags these as HIGH.\n- Private URLs, customer data, or unredacted personal information.\n\n### Coverage matrix\n\n| Dimension | Status | Evidence |\n|---|---|---|\n| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-terraform.jsonl (>=5 should_trigger, >=5 should_not_trigger) |\n| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (`SKILL_PATTERNS[ia-terraform]`) |\n| Reference architecture | n/a | no references; SKILL.md is self-contained |\n| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-terraform/ (created by harvest-sessions) |\n\n## Evaluation\n\nLightweight (run on every change):\n\n```bash\npython3 distillery/scripts/distiller.py validate-plugin --component ia-terraform\npython3 distillery/scripts/distiller.py test-triggers --skill ia-terraform\n```\n\nDeeper (when behavior risk warrants):\n\n```bash\npython3 distill"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns. Skill: ia-terraform Owner: iliaal Summary: Terraform and OpenTofu configuration, modules, testing, state management, and HCL review. Use when working with Terraform, OpenTofu, HCL, tfvars, tftest, state migration, or IaC patterns. Tags: latest:5.0.1 Version history: v5.0.1 | 2026-10-03T17:08:05.450Z | user v5.0.1 v5.0.0 | 2026-09-26T23:22:19.785Z | user v5.0.0 v4.5.3 | 2026-09-13T14:43:05.101Z | user v4.5.3 v4.5.2 |","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1107,"uniquenessScore":55,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T23:34:43.606Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T23:34:43.606Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:41:50.736Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}