Skip to content

Commit ee7a42f

Browse files
refactor(mcp): type evidence responses
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
1 parent c6c4a76 commit ee7a42f

4 files changed

Lines changed: 38 additions & 23 deletions

File tree

internal/mcp/evidence.go

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,32 @@ import (
1414

1515
// workspaceEvidenceFromContext builds evidence metadata for namespace-scoped graph queries.
1616
// @intent include workspace path and git state when available so LLM has traceable provenance.
17-
func (h *handlers) workspaceEvidenceFromContext(ctx context.Context) map[string]any {
17+
func (h *handlers) workspaceEvidenceFromContext(ctx context.Context) workspaceEvidenceBlock {
1818
ns := ctxns.FromContext(ctx)
1919
return h.workspaceEvidence(ns)
2020
}
2121

22+
// workspaceEvidenceBlock captures stable workspace provenance fields shared across MCP responses.
23+
// @intent keep evidence payloads typed while preserving the legacy namespace/workspace/git JSON shape.
24+
type workspaceEvidenceBlock struct {
25+
Namespace string `json:"namespace"`
26+
WorkspacePath string `json:"workspace_path,omitempty"`
27+
Git *workspaceGitEvidenceBlock `json:"git,omitempty"`
28+
}
29+
30+
// workspaceGitEvidenceBlock captures git provenance attached to workspace evidence.
31+
// @intent preserve the legacy git evidence keys while making nil-versus-false behavior explicit.
32+
type workspaceGitEvidenceBlock struct {
33+
Branch string `json:"branch"`
34+
Commit string `json:"commit"`
35+
Dirty *bool `json:"dirty,omitempty"`
36+
Remote string `json:"remote,omitempty"`
37+
}
38+
2239
// @intent collect namespace-scoped workspace and git provenance so MCP responses can explain where graph evidence came from.
23-
func (h *handlers) workspaceEvidence(namespace string) map[string]any {
40+
func (h *handlers) workspaceEvidence(namespace string) workspaceEvidenceBlock {
2441
ns := ctxns.Normalize(namespace)
25-
evidence := map[string]any{"namespace": ns}
42+
evidence := workspaceEvidenceBlock{Namespace: ns}
2643

2744
root := h.deps.WorkspaceRoot
2845
if root == "" {
@@ -35,17 +52,17 @@ func (h *handlers) workspaceEvidence(namespace string) map[string]any {
3552
return evidence
3653
}
3754

38-
evidence["workspace_path"] = workspacePath
55+
evidence.WorkspacePath = workspacePath
3956

4057
gitInfo := workspaceGitEvidence(workspacePath)
41-
if len(gitInfo) > 0 {
42-
evidence["git"] = gitInfo
58+
if gitInfo != nil {
59+
evidence.Git = gitInfo
4360
}
4461
return evidence
4562
}
4663

4764
// @intent summarize git branch, commit, remote, and dirty state for workspace-scoped evidence blocks.
48-
func workspaceGitEvidence(path string) map[string]any {
65+
func workspaceGitEvidence(path string) *workspaceGitEvidenceBlock {
4966
repo, err := git.PlainOpenWithOptions(path, &git.PlainOpenOptions{DetectDotGit: true})
5067
if err != nil {
5168
return nil
@@ -56,15 +73,16 @@ func workspaceGitEvidence(path string) map[string]any {
5673
return nil
5774
}
5875

59-
info := map[string]any{
60-
"branch": branchNameForRef(head.Name()),
61-
"commit": head.Hash().String(),
76+
info := &workspaceGitEvidenceBlock{
77+
Branch: branchNameForRef(head.Name()),
78+
Commit: head.Hash().String(),
6279
}
6380

6481
wt, err := repo.Worktree()
6582
if err == nil {
6683
if status, err := wt.Status(); err == nil {
67-
info["dirty"] = !status.IsClean()
84+
dirty := !status.IsClean()
85+
info.Dirty = &dirty
6886
}
6987
}
7088

@@ -83,16 +101,13 @@ func workspaceGitEvidence(path string) map[string]any {
83101
remoteURL = r.URLs[0]
84102
break
85103
}
104+
}
105+
}
106+
if remoteURL != "" {
107+
info.Remote = remoteURL
86108
}
87109
}
88-
if remoteURL != "" {
89-
info["remote"] = remoteURL
90-
}
91-
}
92110

93-
if len(info) == 0 {
94-
return nil
95-
}
96111
return info
97112
}
98113

internal/mcp/handler_analysis.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ type traceFlowResponse struct {
6666
Name string `json:"name"`
6767
Members []traceFlowMember `json:"members"`
6868
Metadata traceFlowMetadata `json:"metadata"`
69-
Evidence map[string]any `json:"evidence"`
69+
Evidence workspaceEvidenceBlock `json:"evidence"`
7070
}
7171

7272
// detectChangesEntry summarizes one changed node plus its diff-derived risk score.

internal/mcp/handler_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ type minimalContextResponse struct {
6767
TopFlows []minimalContextFlowInfo `json:"top_flows"`
6868
DerivedState map[string]any `json:"derived_state"`
6969
SuggestedTools []string `json:"suggested_tools"`
70-
Evidence map[string]any `json:"evidence"`
70+
Evidence workspaceEvidenceBlock `json:"evidence"`
7171
}
7272

7373
// getMinimalContext returns a compact project snapshot with risk hints and suggested tools.

internal/mcp/handler_query.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ type queryGraphResponse struct {
9292
Target string `json:"target"`
9393
Results []queryGraphResultItem `json:"results"`
9494
Metadata queryGraphMetadata `json:"metadata"`
95-
Evidence map[string]any `json:"evidence"`
95+
Evidence workspaceEvidenceBlock `json:"evidence"`
9696
}
9797

9898
// searchResultItem summarizes one node hit returned by full-text search.
@@ -124,7 +124,7 @@ type nodeResponse struct {
124124
StartLine int `json:"start_line"`
125125
EndLine int `json:"end_line"`
126126
Language string `json:"language"`
127-
Evidence map[string]any `json:"evidence"`
127+
Evidence workspaceEvidenceBlock `json:"evidence"`
128128
}
129129

130130
// getNode returns detailed metadata for a graph node by qualified name.
@@ -597,7 +597,7 @@ type listGraphStatsResponse struct {
597597
NodesByKind map[string]int64 `json:"nodes_by_kind"`
598598
NodesByLanguage map[string]int64 `json:"nodes_by_language"`
599599
EdgesByKind map[string]int64 `json:"edges_by_kind"`
600-
Evidence map[string]any `json:"evidence"`
600+
Evidence workspaceEvidenceBlock `json:"evidence"`
601601
}
602602

603603
// listGraphStats returns aggregate node and edge statistics for the graph.

0 commit comments

Comments
 (0)