Skip to content

feat(temporal): orphan/integrity detection + analyze temporal_orphans tool - #88

Merged
zzet merged 2 commits into
zzet:mainfrom
avfirsov:pr/temporal-orphan-detection
Jun 15, 2026
Merged

feat(temporal): orphan/integrity detection + analyze temporal_orphans tool#88
zzet merged 2 commits into
zzet:mainfrom
avfirsov:pr/temporal-orphan-detection

Conversation

@avfirsov

Copy link
Copy Markdown
Contributor

What

Adds Temporal integrity / orphan detection plus an analyze kind=temporal_orphans MCP tool, and excludes test-file dispatchers from the broken_dispatch count.

Two commits:

  1. Orphan detection + MCP tool — surfaces Temporal integrity gaps from the graph: broken_dispatch, signal_no_handler, query_no_handler, orphan_activity, orphan_workflow. Exposed via analyze kind=temporal_orphans (MCP + CLI). New internal/resolver/temporal_orphans.go.
  2. Exclude test-file dispatchers — dispatch calls originating in *_test files were inflating broken_dispatch as false positives; a small testpath helper filters them out.

Why

Gives a single, graph-grounded answer to "what Temporal wiring is broken?" — unresolved activity/workflow dispatches, signals/queries with no handler, and registered-but-never-dispatched handlers — without manual grepping. The test-file filter keeps the headline number trustworthy.

Tests

New unit + table tests: temporal_orphans_test.go, temporal_orphans_testfilter_test.go, tools_analyze_temporal_test.go. go build ./... clean; internal/resolver and internal/mcp suites pass.

Notes

Self-contained — only new files plus a tool registration; no changes to existing resolution behavior beyond the test-file exclusion.

avfirsov and others added 2 commits June 14, 2026 23:19
… MCP tool

Closes the loop with integrity analysis (no dedicated ContractTemporal —
temporal lives as EdgeCalls+via-meta and blast-radius already traverses it
generically).

- resolver.DetectTemporalOrphans walks the resolved graph for four gaps:
  broken_dispatch (a temporal.stub still pointing at a placeholder — a
  workflow dispatches a non-existent activity/child-workflow),
  signal_no_handler / query_no_handler (a signal sent / query called with
  a name no workflow handles), and orphan_activity / orphan_workflow
  (registered but never dispatched/started — dead code).
- MCP: analyze kind=temporal_orphans surfaces it (handleAnalyzeTemporalOrphans).

Unit test (resolver) + handler test (mcp).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A dispatch whose call site is a test file (*_test.go, *Test.java, files under tests/, ...) is almost always a fixture or mock; counting it as a broken_dispatch is the dominant false positive. DetectTemporalOrphans now skips such dispatches, keyed on the stub edge's own FilePath via a new isTestFilePath predicate (port of indexer.IsTestFile; the resolver cannot import indexer). Only unresolved dispatches are affected; resolved test->activity edges keep their consumed bookkeeping. Robust under incremental reindex (pure function of the path, no Meta dependency).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
func (s *Server) handleAnalyze(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
kind, err := req.RequireString("kind")
if err != nil {
return mcp.NewToolResultError("kind is required (one of: dead_code, hotspots, cycles, would_create_cycle, todos, blame, coverage, stale_code, ownership, coverage_gaps, stale_flags, releases, cgo_users, wasm_users, orphan_tables, unreferenced_tables, coverage_summary, channel_ops, def_use, goroutine_spawns, field_writers, race_writes, unclosed_channels, unsafe_patterns, health_score, annotation_users, config_readers, event_emitters, pubsub, string_emitters, error_surface, log_events, sql_rebuild, external_calls, synthesizers, resolution_outcomes, retrieval_log, routes, models, components, k8s_resources, images, kustomize, cross_repo, impact, named, tests_as_edges, connectivity_health, pagerank, louvain, wcc, scc, kcore)"), nil

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@avfirsov the 1-line fix needed for the PR (add temporal_orphans to the analyze usage string)

@zzet
zzet merged commit ba83b8e into zzet:main Jun 15, 2026
10 checks passed
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