← back to Cli Printing Press
fix(cli): accept backtick raw-string Use: in dogfood walkers (#1169)
7ba9c20a352c473cdffa8db492543a719f1518d2 · 2026-05-12 01:15:22 -0700 · Trevin Chow
* fix(cli): accept backtick raw-string Use: in dogfood walkers
The dogfood novel-features walker, reimplementation check, scorecard
helper, naming check, and command-tree walker all extracted the Cobra
Use: leaf with a regex that only matched the double-quoted form.
Commands declared with Go's backtick raw-string Use: (idiomatic when
the value contains a literal double-quote, e.g. `query "<sql>"`) were
silently reported as missing even when wired and working.
Extend the shared `cobraUseLeafRe` to accept either delimiter and
consolidate the parallel inline regexes onto it so future drift can't
reintroduce the silent miss. Pin the new behavior with tests for each
affected walker.
* docs(cli): note why checkNamingConsistency keeps a separate Use: regex
Greptile flagged the residual divergence from cobraUseLeafRe at
dogfood.go:1072 as a future-drift risk. The capture class is
deliberately tighter ([A-Za-z][A-Za-z0-9_-]* identifiers only) because
the naming check judges verb-shaped tokens, and a broader class would
let flag tokens or angle-bracket args masquerade as verbs. Spell that
out inline so the next reader doesn't try to consolidate it.
Files touched
M internal/pipeline/dogfood.goM internal/pipeline/dogfood_test.goM internal/pipeline/reimplementation_check.goM internal/pipeline/reimplementation_check_test.goM internal/pipeline/scorecard.go
Diff
commit 7ba9c20a352c473cdffa8db492543a719f1518d2
Author: Trevin Chow <trevin@trevinchow.com>
Date: Tue May 12 01:15:22 2026 -0700
fix(cli): accept backtick raw-string Use: in dogfood walkers (#1169)
* fix(cli): accept backtick raw-string Use: in dogfood walkers
The dogfood novel-features walker, reimplementation check, scorecard
helper, naming check, and command-tree walker all extracted the Cobra
Use: leaf with a regex that only matched the double-quoted form.
Commands declared with Go's backtick raw-string Use: (idiomatic when
the value contains a literal double-quote, e.g. `query "<sql>"`) were
silently reported as missing even when wired and working.
Extend the shared `cobraUseLeafRe` to accept either delimiter and
consolidate the parallel inline regexes onto it so future drift can't
reintroduce the silent miss. Pin the new behavior with tests for each
affected walker.
* docs(cli): note why checkNamingConsistency keeps a separate Use: regex
Greptile flagged the residual divergence from cobraUseLeafRe at
dogfood.go:1072 as a future-drift risk. The capture class is
deliberately tighter ([A-Za-z][A-Za-z0-9_-]* identifiers only) because
the naming check judges verb-shaped tokens, and a broader class would
let flag tokens or angle-bracket args masquerade as verbs. Spell that
out inline so the next reader doesn't try to consolidate it.
---
internal/pipeline/dogfood.go | 17 ++--
internal/pipeline/dogfood_test.go | 99 ++++++++++++++++++++++++
internal/pipeline/reimplementation_check.go | 2 +-
internal/pipeline/reimplementation_check_test.go | 40 ++++++++++
internal/pipeline/scorecard.go | 9 ++-
5 files changed, 157 insertions(+), 10 deletions(-)
diff --git a/internal/pipeline/dogfood.go b/internal/pipeline/dogfood.go
index 6b3653be..8c8dd3ab 100644
--- a/internal/pipeline/dogfood.go
+++ b/internal/pipeline/dogfood.go
@@ -496,7 +496,7 @@ func collectRegisteredCommands(dir string) (paths, leaves map[string]bool) {
// (Execute / helpers) isn't a new*Cmd constructor.
rootAddRe := regexp.MustCompile(`rootCmd\.AddCommand\(\s*(new\w+Cmd)\b`)
funcHeaderRe := regexp.MustCompile(`func\s+(new\w+Cmd)\s*\(`)
- useRe := regexp.MustCompile(`Use:\s*"([^"\s]+)`)
+ useRe := cobraUseLeafRe
addChildRe := regexp.MustCompile(`\.AddCommand\(\s*(new\w+Cmd)\b`)
for _, file := range files {
@@ -1066,9 +1066,16 @@ func checkNamingConsistency(dir string) NamingCheckResult {
result := NamingCheckResult{Checked: len(files)}
// Extract the first token of a cobra Use: declaration:
- // Use: "get", -> "get"
- // Use: "list [id]", -> "list"
- useRe := regexp.MustCompile(`(?m)Use:\s*"([A-Za-z][A-Za-z0-9_-]*)`)
+ // Use: "get", -> "get"
+ // Use: "list [id]", -> "list"
+ // Use: `query "<sql>"`, -> "query"
+ //
+ // Deliberately not consolidated onto cobraUseLeafRe: the naming check
+ // only judges identifier-shaped verbs, so the capture class is tightened
+ // to [A-Za-z][A-Za-z0-9_-]* — anything broader would let a flag token
+ // or angle-bracket arg masquerade as a verb. Both regexes accept the
+ // same delimiters; only the capture differs.
+ useRe := regexp.MustCompile("(?m)Use:\\s*[\"`]([A-Za-z][A-Za-z0-9_-]*)")
// Extract long-form flag names from the common cobra registration
// patterns: StringVar, BoolVar, IntVar, Int64Var, StringVarP, BoolVarP,
@@ -1921,7 +1928,7 @@ func checkCommandTree(dir string) CommandTreeResult {
// A constructor is func newXxxCmd(...) — we extract both the function name
// and the cobra Use: field (the command name users see).
constructorRe := regexp.MustCompile(`(?m)^func\s+(new\w+Cmd)\s*\(`)
- useFieldRe := regexp.MustCompile(`(?m)Use:\s*"([^"\s]+)`)
+ useFieldRe := cobraUseLeafRe
type cmdDef struct {
constructor string // e.g. "newBookingsCmd"
diff --git a/internal/pipeline/dogfood_test.go b/internal/pipeline/dogfood_test.go
index 41e7339a..473b0819 100644
--- a/internal/pipeline/dogfood_test.go
+++ b/internal/pipeline/dogfood_test.go
@@ -388,6 +388,33 @@ func newOrphanCmd() { cmd := &cobra.Command{Use: "orphan"} }
assert.Equal(t, []string{"orphan"}, result.Unregistered)
}
+// TestCheckCommandTree_BacktickUse pins that the constructor walker reads
+// the Use: leaf name from a backtick raw-string literal, which authors reach
+// for when the command name contains a literal double-quote. Without
+// backtick support, useName silently falls back to the constructor name
+// and the command surfaces with the wrong identity in CommandTreeResult.
+func TestCheckCommandTree_BacktickUse(t *testing.T) {
+ dir := t.TempDir()
+ cliDir := filepath.Join(dir, "internal", "cli")
+ require.NoError(t, os.MkdirAll(cliDir, 0o755))
+
+ writeTestFile(t, filepath.Join(cliDir, "root.go"), `package cli
+func newRootCmd() {
+ rootCmd.AddCommand(newQueryCmd())
+}
+`)
+ writeTestFile(t, filepath.Join(cliDir, "query.go"),
+ "package cli\n"+
+ "func newQueryCmd() *cobra.Command {\n"+
+ "\treturn &cobra.Command{Use: `query <project> \"<sql>\"`}\n"+
+ "}\n")
+
+ result := checkCommandTree(dir)
+ assert.Equal(t, 1, result.Defined)
+ assert.Equal(t, 1, result.Registered)
+ assert.Empty(t, result.Unregistered)
+}
+
func TestCheckCommandTree_DeeplyNested(t *testing.T) {
dir := t.TempDir()
cliDir := filepath.Join(dir, "internal", "cli")
@@ -1012,6 +1039,36 @@ func newHealthCmd() *cobra.Command {
})
}
+// TestCheckNovelFeatures_BacktickUse pins that the walker matches commands
+// declared with Go's backtick raw-string Use: form. Authors reach for
+// backticks when the command name contains a literal double-quote (e.g.,
+// `query <project> "<sql>"`), and the walker must not silently report
+// those as missing.
+func TestCheckNovelFeatures_BacktickUse(t *testing.T) {
+ cliDir := t.TempDir()
+ cliCodeDir := filepath.Join(cliDir, "internal", "cli")
+ require.NoError(t, os.MkdirAll(cliCodeDir, 0o755))
+ writeTestFile(t, filepath.Join(cliCodeDir, "query.go"),
+ "package cli\n"+
+ "func newQueryCmd() *cobra.Command {\n"+
+ "\treturn &cobra.Command{Use: `query <project> \"<sql>\"`}\n"+
+ "}\n")
+
+ researchDir := t.TempDir()
+ research := &ResearchResult{
+ APIName: "test",
+ NovelFeatures: []NovelFeature{
+ {Name: "SQL query", Command: "query"},
+ },
+ }
+ require.NoError(t, writeResearchJSON(research, researchDir))
+
+ result := checkNovelFeatures(cliDir, researchDir)
+ assert.Equal(t, 1, result.Planned)
+ assert.Equal(t, 1, result.Found)
+ assert.Empty(t, result.Missing)
+}
+
func TestCheckNovelFeatures_ZeroSurvivors(t *testing.T) {
// All planned features missing — novel_features_built should be a non-nil
// empty slice (not omitted), so the fallback to the aspirational list
@@ -1399,6 +1456,48 @@ func newCmd() *cobra.Command {
assert.Empty(t, result.Violations, "--yes is allowed; only --skip-confirmations variants are banned")
}
+// TestCheckNamingConsistency_BacktickUse pins that the verb extractor reads
+// the leading identifier from a backtick raw-string Use: declaration. A
+// banned verb hidden in a backtick literal must still surface as a
+// violation; symmetrically, a permitted verb in the same form must not
+// produce a false positive.
+func TestCheckNamingConsistency_BacktickUse(t *testing.T) {
+ t.Run("permitted verb in backtick Use", func(t *testing.T) {
+ dir := t.TempDir()
+ require.NoError(t, os.MkdirAll(filepath.Join(dir, "internal", "cli"), 0o755))
+ writeTestFile(t, filepath.Join(dir, "internal", "cli", "cmd.go"),
+ "package cli\n"+
+ "\n"+
+ "import \"github.com/spf13/cobra\"\n"+
+ "\n"+
+ "func newQueryCmd() *cobra.Command {\n"+
+ "\treturn &cobra.Command{Use: `query <project> \"<sql>\"`}\n"+
+ "}\n")
+
+ result := checkNamingConsistency(dir)
+ assert.Equal(t, 1, result.Checked)
+ assert.Empty(t, result.Violations)
+ })
+
+ t.Run("banned verb in backtick Use", func(t *testing.T) {
+ dir := t.TempDir()
+ require.NoError(t, os.MkdirAll(filepath.Join(dir, "internal", "cli"), 0o755))
+ writeTestFile(t, filepath.Join(dir, "internal", "cli", "cmd.go"),
+ "package cli\n"+
+ "\n"+
+ "import \"github.com/spf13/cobra\"\n"+
+ "\n"+
+ "func newInfoCmd() *cobra.Command {\n"+
+ "\treturn &cobra.Command{Use: `info <project> \"<filter>\"`}\n"+
+ "}\n")
+
+ result := checkNamingConsistency(dir)
+ require.Len(t, result.Violations, 1)
+ assert.Equal(t, "info", result.Violations[0].Banned)
+ assert.Equal(t, "verb", result.Violations[0].Category)
+ })
+}
+
func TestCheckNamingConsistency_NoFalsePositiveOnIdentifierWithBannedSubstring(t *testing.T) {
dir := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(dir, "internal", "cli"), 0o755))
diff --git a/internal/pipeline/reimplementation_check.go b/internal/pipeline/reimplementation_check.go
index 2dde2d4b..514851eb 100644
--- a/internal/pipeline/reimplementation_check.go
+++ b/internal/pipeline/reimplementation_check.go
@@ -178,7 +178,7 @@ func checkReimplementation(cliDir, researchDir string) ReimplementationCheckResu
"doctor.go": true,
"auth.go": true,
}
- useLineRe := regexp.MustCompile(`Use:\s*"([^"\s]+)`)
+ useLineRe := cobraUseLeafRe
for _, e := range entries {
name := e.Name()
if e.IsDir() || !strings.HasSuffix(name, ".go") {
diff --git a/internal/pipeline/reimplementation_check_test.go b/internal/pipeline/reimplementation_check_test.go
index 5ec301d1..1f260a0e 100644
--- a/internal/pipeline/reimplementation_check_test.go
+++ b/internal/pipeline/reimplementation_check_test.go
@@ -510,6 +510,46 @@ func newFakeCmd(flags *rootFlags) *cobra.Command {
}
}
+// TestCheckReimplementation_BacktickUse pins that the file index recognizes
+// commands declared with Go's backtick raw-string Use: form. Authors reach
+// for backticks when the command name contains a literal double-quote
+// (e.g., `query <project> "<sql>"`); without backtick support the file
+// drops out of leafToFiles and the reimplementation check silently skips
+// the command entirely.
+func TestCheckReimplementation_BacktickUse(t *testing.T) {
+ files := map[string]string{
+ "query.go": "package cli\n" +
+ "\n" +
+ "import \"github.com/spf13/cobra\"\n" +
+ "\n" +
+ "func newQueryCmd(flags *rootFlags) *cobra.Command {\n" +
+ "\treturn &cobra.Command{\n" +
+ "\t\tUse: `query <project> \"<sql>\"`,\n" +
+ "\t\tRunE: func(cmd *cobra.Command, args []string) error {\n" +
+ "\t\t\tc, err := flags.newClient()\n" +
+ "\t\t\tif err != nil { return err }\n" +
+ "\t\t\t_ = c\n" +
+ "\t\t\treturn nil\n" +
+ "\t\t},\n" +
+ "\t}\n" +
+ "}\n",
+ }
+ cliDir, pipelineDir := seedReimplementationFixture(t, files, []NovelFeature{
+ {Name: "SQL query", Command: "query"},
+ })
+
+ got := checkReimplementation(cliDir, pipelineDir)
+ if got.Skipped {
+ t.Fatalf("expected non-skipped result, got Skipped=true (backtick Use: not indexed)")
+ }
+ if got.Checked != 1 {
+ t.Fatalf("Checked: want 1, got %d", got.Checked)
+ }
+ if len(got.Suspicious) != 0 {
+ t.Fatalf("Suspicious: want 0, got %d (%v)", len(got.Suspicious), got.Suspicious)
+ }
+}
+
// Skip path: when research.json is missing the check returns Skipped
// rather than crashing.
func TestCheckReimplementation_NoResearchDir_Skipped(t *testing.T) {
diff --git a/internal/pipeline/scorecard.go b/internal/pipeline/scorecard.go
index 85cddb59..b2813303 100644
--- a/internal/pipeline/scorecard.go
+++ b/internal/pipeline/scorecard.go
@@ -1152,10 +1152,11 @@ func scoreVision(dir string) int {
return score
}
-// cobraUseLeafRe extracts the first whitespace-delimited token from a Cobra
-// `Use: "..."` literal — the leaf command name (e.g., `"trajectory <slug>"`
-// → `trajectory`).
-var cobraUseLeafRe = regexp.MustCompile(`Use:\s*"([^"\s]+)`)
+// cobraUseLeafRe extracts the leaf command name from a Cobra Use: literal.
+// Accepts both Go string forms — double-quoted and backtick raw-string —
+// because authors reach for backticks when the value contains a literal
+// double-quote.
+var cobraUseLeafRe = regexp.MustCompile("Use:\\s*[\"`]([^\"`\\s]+)")
// manifestNovelFeatureLeaves returns the leaves of every novel_features[].command
// in dir/.printing-press.json. Returns nil when the manifest is missing,
← f88a10b3 fix(cli): preserve novel-command keys in --compact partial-s
·
back to Cli Printing Press
·
fix(cli): handle PascalCase .NET-shape API responses in sync 84138f91 →