Skip to content

feat(temporal): resolve wrapper-forwarded activity/workflow dispatch#85

Draft
avfirsov wants to merge 1 commit into
zzet:mainfrom
avfirsov:feat/temporal-wrapper-dispatch
Draft

feat(temporal): resolve wrapper-forwarded activity/workflow dispatch#85
avfirsov wants to merge 1 commit into
zzet:mainfrom
avfirsov:feat/temporal-wrapper-dispatch

Conversation

@avfirsov

Copy link
Copy Markdown
Contributor

What

Resolves Temporal dispatch where the activity/workflow name is forwarded through a thin wrapper function:

func execAct(ctx workflow.Context, name string, in any) workflow.Future {
    return workflow.ExecuteActivity(ctx, name, in)   // name is a parameter
}
// caller:
execAct(ctx, "ChargeCard", in)                       // the literal lives at the call site

The wrapper's ExecuteActivity has no literal name (it's a parameter), so today the caller's "ChargeCard" is lost and the dispatch stays unresolved. This recovers it.

How

Extractor (golang.go / golang_temporal.go):

  • stamp temporal_name_param on a dispatch stub when the name argument is one of the enclosing function's parameters — this marks the function as a name-forwarding wrapper;
  • attach arg_names + callee to call edges so the resolver can read the literal a caller passes at the wrapper's name position (matched by resolved node, or by callee name for cross-package calls).

Resolver (temporal_calls.go):

  • resolveTemporalWrapperCalls discovers wrappers, finds their call sites, and mints a temporal.stub edge on the caller carrying the forwarded literal name. It runs at the top of ResolveTemporalCalls, so the existing stub-resolution sweep then lands those on the registered handler. Idempotent; small helpers argNameAt / metaIntValue / temporalWrapperStubExists.

Scope

  • Single level only. Depth>1 wrapper chains (a wrapper calling a wrapper) are intentionally out of scope — a candidate for a follow-up.
  • Cross-language / const-deref / env-default resolution is untouched — this only adds the wrapper path.

Tests

  • resolver unit (wrapper stub + arg_names call site → resolved edge),
  • extractor unit (temporal_name_param on the wrapper stub; arg_names/callee on the caller edge),
  • end-to-end index→resolve test on real Go source.

go build ./... and go test -race ./internal/resolver/... ./internal/parser/languages/... ./internal/indexer/... pass.

🤖 Generated with Claude Code

Resolve Temporal dispatch where the activity/workflow name is forwarded
through a thin wrapper function:

    func execAct(ctx workflow.Context, name string, in any) workflow.Future {
        return workflow.ExecuteActivity(ctx, name, in)   // name is a param
    }
    execAct(ctx, "ChargeCard", in)                       // literal at call site

The wrapper's dispatch has no literal name (it's a parameter), so the
caller's "ChargeCard" was previously lost. This recovers it (single level).

Extractor (golang.go / golang_temporal.go):
- stamp `temporal_name_param` on a dispatch stub when the name argument is
  one of the enclosing function's parameters (marks the func as a wrapper);
- attach `arg_names` + `callee` to call edges so the resolver can read the
  literal a caller passes at the wrapper's name position.

Resolver (temporal_calls.go):
- `resolveTemporalWrapperCalls` discovers wrappers (stub edges carrying
  `temporal_name_param`), matches their call sites (by resolved node or by
  callee name for cross-package calls), and mints a `temporal.stub` edge on
  the caller with the forwarded literal name. Called at the top of
  `ResolveTemporalCalls` so the existing sweep then resolves those stubs to
  the registered handler. Idempotent; helpers `argNameAt`, `metaIntValue`,
  `temporalWrapperStubExists`.

Single level only — depth>1 wrapper chains are intentionally out of scope.
Cross-language / const-deref / env-default resolution is untouched.

Tests: resolver unit, extractor unit (param-stub + arg_names), and an
end-to-end index→resolve test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@avfirsov avfirsov force-pushed the feat/temporal-wrapper-dispatch branch from fb652a1 to d15fa72 Compare June 13, 2026 09:07
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.

1 participant