Skip to content

feat(temporal): LLM cleaning pass — analyze kind=temporal_verify - #96

Merged
zzet merged 4 commits into
zzet:mainfrom
avfirsov:pr/temporal-verify
Jun 15, 2026
Merged

feat(temporal): LLM cleaning pass — analyze kind=temporal_verify#96
zzet merged 4 commits into
zzet:mainfrom
avfirsov:pr/temporal-verify

Conversation

@avfirsov

Copy link
Copy Markdown
Contributor

What

Adds an LLM "cleaning pass" for Temporal dispatch edges, invocable via analyze kind=temporal_verify: it re-checks low-confidence temporal edges against the actual source via an LLM and returns a promote / suppress / keep verdict per edge (it reports verdicts; it does not mutate the stored graph unless wired to).

  • internal/resolver/temporal_verify.go — deterministic core VerifyTemporalEdges over the graph, with injected TemporalVerifier / TemporalSourceProvider interfaces (no I/O in the core).
  • internal/analyzer/temporal_verify.go — an llm.Provider-backed verifier + file source provider + disk verdict cache + VerifyReportToMap.
  • internal/mcp/tools_analyze_temporal_verify.go — the analyze kind=temporal_verify MCP handler: obtains the server's live LLM provider, runs the pass over the active graph, returns the report. With no LLM configured it returns a clear error ("set llm.provider …"), never panics.

Result keys: checked, confirmed, rejected, uncertain, errors, details[], totals. Supports compact, format, max_bytes.

Why

Synthesized temporal edges (wrapper-following, convention, env-default, etc.) land at inferred/speculative tiers — some are wrong. This gives a graph-grounded, opt-in LLM verification to promote the right ones and flag the noise, surfaced through the existing analyze surface alongside synthesizers / resolution_outcomes.

Notes

Tests

Core promote/suppress/keep + error-untouched + skip-placeholder (resolver); report-map, verdict-parse, cache hit/persist (analyzer); handler routing + no-LLM clear-error + source-read-via-resolveNodePath (mcp). go build ./..., go vet, resolver/analyzer/mcp suites pass.

avfirsov and others added 2 commits June 15, 2026 10:02
The precision backstop for the aggressive AST recall layers: an LLM, grounded
in real caller+candidate source, verifies each low-confidence Temporal edge and
the pass promotes the confirmed ones, suppresses the rejected ones, and leaves
the uncertain ones — never touching register-confirmed 0.9 edges.

- resolver.VerifyTemporalEdges: deterministic core over edges at confidence
  ≤0.65 (confirmed→0.85 visible, rejected→0.1 hidden, uncertain→unchanged),
  driven by injected TemporalVerifier + TemporalSourceProvider interfaces
  (fully unit-tested with fakes).
- analyzer adapter: llm.Provider-backed verifier (strict-JSON verdict, tolerant
  parse), file-backed source provider, and a disk verdict cache keyed by
  model+name+caller-src+target-src for reproducible / CI-safe re-runs.
- CLI: `gortex analyze --kind temporal_verify` builds the provider in-process
  from llm.* config (daemonless); cache in git-ignored .gortex/. (Also carries
  the allow-list wiring for the analyze path.)
- AGENTS.md: corporate-agent instructions for maintaining the allow-list and
  running the clean pass, with the anonymization protocol.

MCP `analyze kind=temporal_verify` handler is a deferred follow-up (corp flow
is the daemonless CLI).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The temporal LLM cleaning pass (resolver.VerifyTemporalEdges) had no
entrypoint after the CLI analyze host was removed and analyze became
MCP-only. Wire it into the analyze dispatcher.

- analyzer: add NewLLMTemporalVerifierFromProvider so the handler reuses
  the MCP server's live llm.Provider instead of constructing a second one
  from raw config.
- mcp: handleAnalyzeTemporalVerify builds the verifier from
  s.llmService.Provider(), runs VerifyTemporalEdges over the active graph,
  and returns analyzer.VerifyReportToMap(report). With no LLM configured it
  returns a clear "LLM provider" error result rather than no-op'ing or
  panicking. A serverSourceProvider reads node source through the server's
  own resolveNodePath so paths are correct in single-repo, multi-repo, and
  worktree layouts.
- Register the kind in the dispatch switch + the kind description strings.
- Tests: assert routing, the no-LLM-configured clear error, unknown-kind
  fallthrough, and the source-provider read seam.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@avfirsov
avfirsov force-pushed the pr/temporal-verify branch from 91f986a to f53809c Compare June 15, 2026 07:06
avfirsov and others added 2 commits June 15, 2026 16:47
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the temporal_verify LLM pass actually act, not just report:
- VerifyTemporalEdges now PERSISTS promote/suppress verdicts via ReindexEdges,
  so it works on the disk-backed store (where EdgesByKind hands back copies),
  not only the in-memory graph
- runs the LLM verification OUTSIDE the resolve mutex: snapshot candidates
  under the lock, verify unlocked, re-acquire only to apply + persist — so a
  multi-edge pass no longer stalls concurrent resolution/edits
- the MCP handler wraps the verifier in the disk-backed CachingVerifier
  (keyed on provider + source) and Flushes it, so re-runs (CI) skip the LLM
- persistence regression test (re-fetch from the store, not the pointer)
@zzet
zzet merged commit 260f9d5 into zzet:main Jun 15, 2026
9 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