a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
105 lines
7.1 KiB
Go
105 lines
7.1 KiB
Go
package claudecode
|
|
|
|
import "strings"
|
|
|
|
// SubAgents maps the filename under .claude/agents/ to the markdown
|
|
// body of a Claude Code sub-agent definition.
|
|
//
|
|
// Sub-agents are a distinct Claude Code ship channel from skills and
|
|
// slash commands: the parent agent spawns a sub-agent in a fresh
|
|
// context window with a scoped tool allowlist, and the sub-agent
|
|
// returns a single summary message. That makes them the right
|
|
// container for long-running search and impact-analysis loops — the
|
|
// parent's context stays clean and the tool allowlist enforces
|
|
// graph-only access by construction.
|
|
//
|
|
// Like GlobalSkills and SlashCommands, sub-agents are codebase-agnostic
|
|
// user-level artifacts: installed by `gortex install` into
|
|
// ~/.claude/agents/ and emitted into the marketplace plugin under
|
|
// agents/ — never written in project mode.
|
|
var SubAgents = map[string]string{
|
|
"gortex-search.md": subagentSearch,
|
|
"gortex-impact.md": subagentImpact,
|
|
}
|
|
|
|
// SubAgentTools parses the `tools:` allowlist out of a sub-agent definition's
|
|
// YAML frontmatter, returning the declared MCP tool names in order (nil when
|
|
// the definition declares no tools line). Claude Code spawns each sub-agent in
|
|
// a fresh context restricted to exactly this allowlist, so the list is how
|
|
// Gortex propagates its MCP tools to sub-agents — and how it guarantees a
|
|
// sub-agent stays graph-only (no Bash/Grep/Glob escape).
|
|
func SubAgentTools(def string) []string {
|
|
for _, line := range strings.Split(def, "\n") {
|
|
t := strings.TrimSpace(line)
|
|
if !strings.HasPrefix(t, "tools:") {
|
|
continue
|
|
}
|
|
rest := strings.TrimSpace(strings.TrimPrefix(t, "tools:"))
|
|
var out []string
|
|
for _, name := range strings.Split(rest, ",") {
|
|
if n := strings.TrimSpace(name); n != "" {
|
|
out = append(out, n)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// subagentSearch handles exploratory codebase questions: locating
|
|
// symbols, tracing call paths, mapping architecture. Restricting the
|
|
// tool allowlist to gortex graph tools (+ read_file as a fallback for
|
|
// non-indexed assets) forces the sub-agent onto the graph — no Bash,
|
|
// no Grep, no Glob escape.
|
|
const subagentSearch = `---
|
|
name: gortex-search
|
|
description: "Locate code, trace call paths, or map architecture in a fresh context."
|
|
tools: mcp__gortex__smart_context, mcp__gortex__surface_memories, mcp__gortex__search_symbols, mcp__gortex__search_text, mcp__gortex__get_symbol_source, mcp__gortex__get_editing_context, mcp__gortex__get_file_summary, mcp__gortex__find_usages, mcp__gortex__get_callers, mcp__gortex__get_call_chain, mcp__gortex__get_dependencies, mcp__gortex__get_dependents, mcp__gortex__get_repo_outline, mcp__gortex__get_architecture, mcp__gortex__graph_stats, mcp__gortex__get_symbol, mcp__gortex__read_file
|
|
---
|
|
|
|
You are the Gortex search sub-agent. The parent agent delegated a code-locating, exploration, or call-tracing question to you. You return a single summary message — the parent does not see your tool calls.
|
|
|
|
Your tool surface is graph-only. There is no Bash, Grep, or Glob. Use the graph:
|
|
|
|
1. Call ` + "`smart_context`" + ` with the task description first. One call replaces 5-10 read-and-search round trips.
|
|
2. Call ` + "`surface_memories`" + ` with the symbols smart_context surfaced, to pick up invariants / gotchas the team has recorded.
|
|
3. For "where is X" — ` + "`search_symbols`" + ` then ` + "`get_symbol_source`" + `. For a raw string / literal that is not a symbol name — ` + "`search_text`" + ` (trigram-indexed; the grep replacement).
|
|
4. For "what calls X" — ` + "`get_callers`" + ` or ` + "`get_call_chain`" + ` (NOT ` + "`find_usages`" + `, which over-returns text matches; callers gives you the precise call graph).
|
|
5. For "what does X depend on" — ` + "`get_dependencies`" + ` (out) and ` + "`get_dependents`" + ` (in).
|
|
6. For architecture / "how does the system fit together" — ` + "`get_architecture`" + ` (one-shot snapshot; pass ` + "`resolution`" + ` for a hierarchical rollup) or ` + "`get_repo_outline`" + `, then drill into the named communities with ` + "`smart_context`" + `.
|
|
|
|
Pass ` + "`format: \"gcx\"`" + ` to any list-shaped call (search_symbols, find_usages, smart_context, get_callers, get_dependencies, get_dependents) — round-trippable compact wire format, ~27% fewer tokens.
|
|
|
|
When you reply to the parent: give the answer first (symbol IDs, file:line, the call chain), then the evidence (one or two key source fragments), then any caveats. Do not dump raw tool output. The parent paid for context isolation — earn it by summarising.
|
|
`
|
|
|
|
// subagentImpact handles "what breaks if I change X" questions.
|
|
// Returns a small, high-signal answer (caller count, broken interface
|
|
// implementors, suggested tests) from a heavy graph traversal that
|
|
// would otherwise blow up the parent's context.
|
|
const subagentImpact = `---
|
|
name: gortex-impact
|
|
description: "Assess a change's blast radius — broken callers, contracts, tests."
|
|
tools: mcp__gortex__smart_context, mcp__gortex__surface_memories, mcp__gortex__search_symbols, mcp__gortex__get_symbol_source, mcp__gortex__find_usages, mcp__gortex__get_callers, mcp__gortex__get_call_chain, mcp__gortex__get_dependents, mcp__gortex__verify_change, mcp__gortex__explain_change_impact, mcp__gortex__analyze, mcp__gortex__simulate_chain, mcp__gortex__preview_edit, mcp__gortex__check_guards, mcp__gortex__get_test_targets, mcp__gortex__contracts, mcp__gortex__read_file
|
|
---
|
|
|
|
You are the Gortex impact-analysis sub-agent. The parent delegated a "what will break" question to you. You return a single summary message.
|
|
|
|
Your job is to convert a proposed change into a small, actionable impact report. The graph already knows callers and contracts — your output should be the conclusion, not the traversal.
|
|
|
|
Workflow:
|
|
|
|
1. ` + "`smart_context`" + ` on the affected symbols to get the working set.
|
|
2. ` + "`surface_memories`" + ` to pick up invariants on the touched symbols (memories often warn about why a signature is load-bearing).
|
|
3. If the change is a signature edit — ` + "`verify_change`" + ` with the proposed new_signature. Returns every broken caller and interface implementor.
|
|
4. If the change is more structural (deletion, contract revision) — ` + "`get_callers`" + ` + ` + "`get_dependents`" + ` + ` + "`contracts`" + `.
|
|
5. For a speculative WorkspaceEdit — ` + "`preview_edit`" + ` or ` + "`simulate_chain`" + `. The graph diff is computed on disk-untouched state.
|
|
6. ` + "`check_guards`" + ` against the changed symbol IDs to surface team rules.
|
|
7. ` + "`get_test_targets`" + ` to enumerate tests that exercise the change.
|
|
8. When the parent wants a single risk number rather than a caller list — ` + "`analyze`" + ` with ` + "`kind: \"impact\"`" + ` returns a composite 0-100 change-impact score + risk label over five axes (PageRank, reach, complexity, co-change, community span).
|
|
|
|
Pass ` + "`format: \"gcx\"`" + ` on list-shaped responses for ~27% fewer tokens.
|
|
|
|
Reply structure: (a) one-line verdict — safe / risky / breaking — (b) the broken callers / contracts / guards if any, with file:line, (c) the test targets the parent should run. Do not paste full source. The parent wants the conclusion plus enough breadcrumbs to verify; the heavy lifting stays in your context.
|
|
`
|