Summary
For languages where call resolution is intentionally absent, role classification still emits dead-unresolved for every symbol. The verdict is 100% false-positive by construction, and it invites destructive action — an agent or human reading "132 dead symbols" in a Terraform repo may try to delete live infrastructure.
This is not a request for HCL call resolution. The README support matrix is explicit and correct that Terraform/HCL is parse-only (✓ for symbols, —³ for heritage/type-inference/call-graph, footnoted "declarative — no functions, classes, or type system"), and resolution-benchmark.test.ts sets hcl: { precision: 0.0, recall: 0.0 } under the comment "New fixture languages — no parser or call resolution yet". Absence of call edges for HCL is by design. Emitting a dead-code verdict anyway is the defect.
Reproduction
Minimal Terraform file where every resource is actively referenced:
resource "aws_kms_key" "state" { description = "state encryption key" }
resource "aws_s3_bucket" "state" { bucket = "my-state-bucket" }
resource "aws_s3_bucket_server_side_encryption_configuration" "state" {
bucket = aws_s3_bucket.state.id # references aws_s3_bucket.state
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key.state.arn # references aws_kms_key.state
}
}
}
output "bucket_name" { value = aws_s3_bucket.state.bucket } # references aws_s3_bucket.state
$ codegraph build
Native build orchestrator completed: 6 nodes, 5 edges, 1 files
$ codegraph roles
Node roles (4 symbols):
dead-unresolved: 4
## dead-unresolved (4)
- aws_kms_key.state main.tf:1
- aws_s3_bucket.state main.tf:5
- aws_s3_bucket_server_side_encryption_configuration.state main.tf:9
- output.bucket_name main.tf:18
All 4 flagged dead; aws_s3_bucket.state is referenced three times. All 5 edges are contains — there are zero reference edges, as expected for a parse-only language.
Confirmed independently on optave/tenant-optave-autopilot-svc during the org rollout: 129 of its 132 dead-unresolved symbols are .tf, including KMS keys and buckets wired together in the same file.
Also worth noting: the HCL fixture's expected edges never materialize
tests/benchmarks/resolution/fixtures/hcl/expected-edges.json declares 2 calls edges (module.user_service → module.repository, → module.validators). Building that fixture yields 31 nodes, 27 edges, all contains — 0 of 2 expected edges. The benchmark passes only because the HCL threshold is 0.0/0.0. That's self-consistent with parse-only support, but it means the fixture and its manifest currently encode an aspiration no test enforces. Either wire the module-reference edges up, or annotate the manifest as pending so it isn't mistaken for a passing capability.
Suggested fix
Gate dead-code classification on whether the language has call-resolution support. For parse-only languages, either omit dead-* roles entirely or emit a distinct, clearly non-actionable role (e.g. unanalyzed). The language capability is already known — LANGUAGE_REGISTRY in domain/parser.ts is the single source of truth, and the benchmark thresholds already encode which languages have no resolution.
Whatever shape is chosen, apply it to the mirrored Rust path in crates/codegraph-core/src/graph/classifiers/roles.rs so the engines don't diverge.
Why this matters now
The org-wide rollout writes a .codegraph/basics.md health baseline into every Optave repo, including Terraform ones. Right now those baselines have to carry an explicit "ignore this number, it's a false positive" caveat — which is exactly the "documenting a bug as expected behavior" pattern CLAUDE.md warns against.
Related
Summary
For languages where call resolution is intentionally absent, role classification still emits
dead-unresolvedfor every symbol. The verdict is 100% false-positive by construction, and it invites destructive action — an agent or human reading "132 dead symbols" in a Terraform repo may try to delete live infrastructure.This is not a request for HCL call resolution. The README support matrix is explicit and correct that Terraform/HCL is parse-only (
✓for symbols,—³for heritage/type-inference/call-graph, footnoted "declarative — no functions, classes, or type system"), andresolution-benchmark.test.tssetshcl: { precision: 0.0, recall: 0.0 }under the comment "New fixture languages — no parser or call resolution yet". Absence of call edges for HCL is by design. Emitting a dead-code verdict anyway is the defect.Reproduction
Minimal Terraform file where every resource is actively referenced:
All 4 flagged dead;
aws_s3_bucket.stateis referenced three times. All 5 edges arecontains— there are zero reference edges, as expected for a parse-only language.Confirmed independently on
optave/tenant-optave-autopilot-svcduring the org rollout: 129 of its 132dead-unresolvedsymbols are.tf, including KMS keys and buckets wired together in the same file.Also worth noting: the HCL fixture's expected edges never materialize
tests/benchmarks/resolution/fixtures/hcl/expected-edges.jsondeclares 2callsedges (module.user_service→module.repository, →module.validators). Building that fixture yields 31 nodes, 27 edges, allcontains— 0 of 2 expected edges. The benchmark passes only because the HCL threshold is0.0/0.0. That's self-consistent with parse-only support, but it means the fixture and its manifest currently encode an aspiration no test enforces. Either wire the module-reference edges up, or annotate the manifest as pending so it isn't mistaken for a passing capability.Suggested fix
Gate dead-code classification on whether the language has call-resolution support. For parse-only languages, either omit
dead-*roles entirely or emit a distinct, clearly non-actionable role (e.g.unanalyzed). The language capability is already known —LANGUAGE_REGISTRYindomain/parser.tsis the single source of truth, and the benchmark thresholds already encode which languages have no resolution.Whatever shape is chosen, apply it to the mirrored Rust path in
crates/codegraph-core/src/graph/classifiers/roles.rsso the engines don't diverge.Why this matters now
The org-wide rollout writes a
.codegraph/basics.mdhealth baseline into every Optave repo, including Terraform ones. Right now those baselines have to carry an explicit "ignore this number, it's a false positive" caveat — which is exactly the "documenting a bug as expected behavior" patternCLAUDE.mdwarns against.Related