127 lines
3.8 KiB
Go
127 lines
3.8 KiB
Go
package capdiag
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// RenderText formats a human-readable report: Summary → Issues → subsystems.
|
|
func RenderText(r Report) string {
|
|
var b strings.Builder
|
|
fmt.Fprintf(&b, "reasonix doctor capabilities\n")
|
|
fmt.Fprintf(&b, "root: %s live: %v schema: %d\n\n", r.Root, r.Live, r.SchemaVersion)
|
|
|
|
fmt.Fprintf(&b, "Summary\n")
|
|
fmt.Fprintf(&b, " errors=%d warnings=%d infos=%d\n", r.Summary.Errors, r.Summary.Warnings, r.Summary.Infos)
|
|
fmt.Fprintf(&b, " instructions=%d skills=%d commands=%d hooks=%d plugins=%d mcp=%d\n\n",
|
|
r.Summary.Instructions, r.Summary.Skills, r.Summary.Commands,
|
|
r.Summary.Hooks, r.Summary.Plugins, r.Summary.MCPServers)
|
|
|
|
fmt.Fprintf(&b, "Issues (%d)\n", len(r.Issues))
|
|
if len(r.Issues) == 0 {
|
|
b.WriteString(" (none)\n")
|
|
}
|
|
for _, is := range r.Issues {
|
|
fmt.Fprintf(&b, " [%s] %s", is.Severity, is.Code)
|
|
if is.Name != "" {
|
|
fmt.Fprintf(&b, " %s", is.Name)
|
|
}
|
|
fmt.Fprintf(&b, ": %s\n", is.Message)
|
|
if is.Source != "" {
|
|
fmt.Fprintf(&b, " source: %s\n", is.Source)
|
|
}
|
|
if is.Remediation != "" {
|
|
fmt.Fprintf(&b, " fix: %s\n", is.Remediation)
|
|
}
|
|
}
|
|
b.WriteByte('\n')
|
|
|
|
// Instructions
|
|
fmt.Fprintf(&b, "Instructions (%d)\n", len(r.Instructions.Docs))
|
|
for _, d := range r.Instructions.Docs {
|
|
fmt.Fprintf(&b, " %d. [%s] %s\n", d.Order, d.Scope, d.Path)
|
|
}
|
|
if len(r.Instructions.Docs) == 0 {
|
|
b.WriteString(" (none)\n")
|
|
}
|
|
b.WriteByte('\n')
|
|
|
|
writeAsset(&b, "Skills", r.Skills)
|
|
writeAsset(&b, "Commands", r.Commands)
|
|
|
|
fmt.Fprintf(&b, "Hooks (trusted_project=%v project_defines=%v entries=%d)\n",
|
|
r.Hooks.TrustedProject, r.Hooks.ProjectDefines, len(r.Hooks.Entries))
|
|
for _, s := range r.Hooks.Sources {
|
|
fmt.Fprintf(&b, " source [%s] %s status=%s hooks=%d\n", s.Scope, s.Path, s.Status, s.HookCount)
|
|
}
|
|
for _, e := range r.Hooks.Entries {
|
|
fmt.Fprintf(&b, " - %s scope=%s match=%q blocking=%v\n", e.Event, e.Scope, e.Match, e.Blocking)
|
|
}
|
|
b.WriteByte('\n')
|
|
|
|
fmt.Fprintf(&b, "Plugins (%d)\n", len(r.Plugins.Packages))
|
|
for _, p := range r.Plugins.Packages {
|
|
fmt.Fprintf(&b, " - %s enabled=%v status=%s skills=%d commands=%d hooks=%d mcp=%d\n",
|
|
p.Name, p.Enabled, p.Status, p.Skills, p.Commands, p.Hooks, p.MCPServers)
|
|
fmt.Fprintf(&b, " root: %s\n", p.Root)
|
|
}
|
|
if len(r.Plugins.Packages) == 0 {
|
|
b.WriteString(" (none)\n")
|
|
}
|
|
b.WriteByte('\n')
|
|
|
|
fmt.Fprintf(&b, "MCP (%d)\n", len(r.MCP.Servers))
|
|
for _, s := range r.MCP.Servers {
|
|
fmt.Fprintf(&b, " - %s transport=%s intent=%s source=%s", s.Name, s.Transport, s.StartIntent, s.Source)
|
|
if s.RuntimeStatus != "" {
|
|
fmt.Fprintf(&b, " runtime=%s", s.RuntimeStatus)
|
|
}
|
|
if s.ToolCount > 0 {
|
|
fmt.Fprintf(&b, " tools=%d", s.ToolCount)
|
|
}
|
|
b.WriteByte('\n')
|
|
if s.Error != "" {
|
|
fmt.Fprintf(&b, " error: %s\n", s.Error)
|
|
}
|
|
}
|
|
if len(r.MCP.Servers) == 0 {
|
|
b.WriteString(" (none)\n")
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
func writeAsset(b *strings.Builder, title string, a AssetReport) {
|
|
fmt.Fprintf(b, "%s (winners=%d shadowed=%d", title, a.Winners, a.Shadowed)
|
|
if a.Disabled > 0 {
|
|
fmt.Fprintf(b, " disabled=%d", a.Disabled)
|
|
}
|
|
if a.ParseErrors > 0 {
|
|
fmt.Fprintf(b, " errors=%d", a.ParseErrors)
|
|
}
|
|
b.WriteString(")\n")
|
|
for _, r := range a.Roots {
|
|
fmt.Fprintf(b, " root %s status=%s", r.Path, r.Status)
|
|
if r.Scope != "" {
|
|
fmt.Fprintf(b, " scope=%s", r.Scope)
|
|
}
|
|
b.WriteByte('\n')
|
|
}
|
|
for _, e := range a.Entries {
|
|
if e.Status != "winner" && e.Status != "error" {
|
|
continue // keep text output compact; full list is in JSON
|
|
}
|
|
fmt.Fprintf(b, " - %s [%s] %s\n", e.Name, e.Status, e.Path)
|
|
}
|
|
b.WriteByte('\n')
|
|
}
|
|
|
|
// RenderJSON writes indented JSON to a string (for tests / copy).
|
|
func RenderJSON(r Report) (string, error) {
|
|
b, err := json.MarshalIndent(r, "", " ")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(b) + "\n", nil
|
|
}
|