Skip to content

feat(temporal): resolve activity/workflow dispatch names from env-var-with-default vars#79

Merged
zzet merged 1 commit into
zzet:mainfrom
avfirsov:feat/temporal-env-default-names
Jun 12, 2026
Merged

feat(temporal): resolve activity/workflow dispatch names from env-var-with-default vars#79
zzet merged 1 commit into
zzet:mainfrom
avfirsov:feat/temporal-env-default-names

Conversation

@avfirsov

Copy link
Copy Markdown
Contributor

Summary

Resolve a Temporal activity / workflow dispatch name when it comes from a local variable read from an env var with a literal default, instead of leaving the call unresolved — landing the resolved edge at the speculative tier since the runtime env value may differ from the default.

This is one half of a split from #75 (the other half — Go-side query/signal/update handler edges — is in a separate PR so each can be reviewed independently).

Changes

  • When an ExecuteActivity / ExecuteLocalActivity / ExecuteChildWorkflow name argument is a bare identifier assigned, in the enclosing function, from an env-var-with-literal-default, resolve the dispatch to that literal default:
    actName := cmp.Or(os.Getenv("CHARGE_ACTIVITY"), "ChargeCard")
    workflow.ExecuteActivity(ctx, actName, id)   // → activity "ChargeCard"
    
    name := os.Getenv("K"); if name == "" { name = "ChargeCard" }
  • The lookup is narrow and intra-procedural, anchored on a literal os.Getenv / os.LookupEnv read (so the value is provably env-sourced — this is not general constant propagation), and only considers assignments lexically before the call. Anything else is left unresolved, no guessing.
  • The parser tags the stub edge temporal_name_origin=env_default; the resolver then lands it at the speculative tier (OriginSpeculative, confidence 0.4, MetaSpeculative=true) rather than ast_resolved. The edge is present but hidden from default queries, reusing the existing speculative-edge convention (OriginSpeculative / MetaSpeculative, cf. speculative_dispatch.go).

Testing

  • All tests pass (go test -race ./...) for the touched packages (internal/parser/languages, internal/resolver, internal/indexer). The only failures in my environment are the pre-existing internal/indexer watcher tests failing with inotify ... too many open files (a local WSL fd-limit issue, unrelated — no watcher files touched).
  • New tests added — parser-level (go_temporal_test.go: cmp.Or and if x=="" shapes + negative cases for a plain non-env variable and an env read with no literal default), resolver-level (temporal_calls_test.go: speculative-tier resolution + unresolved-stays-placeholder), and end-to-end (temporal_e2e_test.go).
  • Benchmarks — n/a; the lookup is AST-local within the enclosing function and only triggers for a bare-identifier dispatch name.

Checklist

  • Code follows existing patterns in the codebase (reuses the OriginSpeculative / MetaSpeculative tier and confidence-label machinery)
  • No unnecessary abstractions added
  • Language extractor includes Meta["methods"] for interfaces (if applicable) — n/a
  • Methods have EdgeMemberOf edges to their containing type (if applicable) — n/a

Notes for reviewers

This is the more opinionated of the two split PRs: it adds a narrow intra-procedural data-flow shortcut, which is a small departure from the otherwise AST-local detector. It's deliberately bounded (literal os.Getenv/os.LookupEnv anchor, literal default only, lexically-before-the-call) and emitted at the speculative/hidden tier precisely so it can't silently distort the high-confidence graph. Happy to gate it behind a flag or narrow it further if you'd prefer.

…ault vars

When a workflow names its activity/child-workflow through a local variable
read from an env var with a literal fallback, resolve the dispatch to that
literal default instead of leaving it unresolved:

    actName := cmp.Or(os.Getenv("CHARGE_ACTIVITY"), "ChargeCard")
    workflow.ExecuteActivity(ctx, actName, id)   // -> activity "ChargeCard"

    name := os.Getenv("K"); if name == "" { name = "ChargeCard" }

The parser does a narrow, intra-procedural lookup anchored on a literal
os.Getenv / os.LookupEnv read (so the value is provably env-sourced, not a
general data-flow guess) and tags the stub edge temporal_name_origin=
env_default. The resolver then lands the edge at the speculative tier
(OriginSpeculative, confidence 0.4, MetaSpeculative=true) rather than
ast_resolved — the runtime env override may name a different handler than
the literal default, so the edge is present but hidden from default queries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants