package cmd import ( "fmt" "os" "github.com/spf13/cobra" "git.coopcloud.tech/wiki-cafe/member-console/internal/lint" ) var lintCmd = &cobra.Command{ Use: "lint", Short: "Static checks for operator UI integrity (M7f.1)", Long: `lint walks the Go source under internal/server/ and the templates under internal/embeds/templates/ and reports: - dead routes: routeURL patterns with no registered handler - dead swap targets: hx-target="#X" with no matching id="X" - stale tab references: ?tab= was retired in M7d (operator-mpa-conversion) - banned literal URLs: interpolated hx-* URL strings must use routeURL Exits 0 on a clean tree, 1 on violations, 2 on internal errors. Safe to wire into CI or a pre-commit hook. See status/milestones.md (M7f.1) and docs/operator-ux-conventions.md ยง9.`, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { serverDir, _ := cmd.Flags().GetString("server-dir") templateDir, _ := cmd.Flags().GetString("template-dir") walkthroughDir, _ := cmd.Flags().GetString("walkthrough-dir") res, err := lint.Run(lint.Config{ ServerDir: serverDir, TemplateDir: templateDir, WalkthroughDir: walkthroughDir, }) if err != nil { fmt.Fprintf(os.Stderr, "lint: %v\n", err) os.Exit(2) } for _, v := range res.Violations { fmt.Fprintf(os.Stderr, "%s:%d: [%s] %s\n", v.File, v.Line, v.Rule, v.Message) } if len(res.Violations) > 0 { fmt.Fprintf(os.Stderr, "\nlint: %d violation(s) across %d routes / %d URL refs\n", len(res.Violations), res.RoutesScanned, res.URLRefsScanned) os.Exit(1) } fmt.Fprintf(os.Stderr, "lint: ok (%d routes, %d URL refs)\n", res.RoutesScanned, res.URLRefsScanned) }, } func init() { lintCmd.Flags().String("server-dir", "internal/server", "Go source directory containing mux.HandleFunc registrations") lintCmd.Flags().String("template-dir", "internal/embeds/templates", "Embedded templates directory") lintCmd.Flags().String("walkthrough-dir", "test/e2e/operator-walkthroughs", `Walkthrough directory for coverage rule (set "-" to disable)`) rootCmd.AddCommand(lintCmd) }