[object Object]

← back to Cli Printing Press

fix(cli): scorecard APIName drops binary suffix (#489)

c76d3ec98137dd13d566a161f886f9eace8f608d · 2026-05-01 21:34:35 -0700 · Trevin Chow

RunScorecard set sc.APIName = filepath.Base(outputDir). The full pipeline
(fullrun.go:256) passes paths.WorkingCLIDir, which is always -pp-cli
suffixed; library checkouts share the same shape. APIName then landed
suffixed in two user-visible places — the Markdown scorecard header
("# Scorecard: producthunt-pp-cli") and the CLI's "Quality Scorecard:"
line — conflating the API slug with the binary name.

Strip the suffix via naming.TrimCLISuffix, matching the established
idiom (runtime.go:116, emboss.go:245) and the recently-fixed mcp-sync
slug derivation. Bare-slug paths (local library convention) pass
through unchanged; legacy -cli and numeric rerun suffixes get the same
treatment as everywhere else.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit c76d3ec98137dd13d566a161f886f9eace8f608d
Author: Trevin Chow <trevin@trevinchow.com>
Date:   Fri May 1 21:34:35 2026 -0700

    fix(cli): scorecard APIName drops binary suffix (#489)
    
    RunScorecard set sc.APIName = filepath.Base(outputDir). The full pipeline
    (fullrun.go:256) passes paths.WorkingCLIDir, which is always -pp-cli
    suffixed; library checkouts share the same shape. APIName then landed
    suffixed in two user-visible places — the Markdown scorecard header
    ("# Scorecard: producthunt-pp-cli") and the CLI's "Quality Scorecard:"
    line — conflating the API slug with the binary name.
    
    Strip the suffix via naming.TrimCLISuffix, matching the established
    idiom (runtime.go:116, emboss.go:245) and the recently-fixed mcp-sync
    slug derivation. Bare-slug paths (local library convention) pass
    through unchanged; legacy -cli and numeric rerun suffixes get the same
    treatment as everywhere else.
    
    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 internal/pipeline/scorecard.go                |  7 ++++++-
 internal/pipeline/scorecard_artifacts_test.go | 22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/internal/pipeline/scorecard.go b/internal/pipeline/scorecard.go
index 1c773f79..c775bd61 100644
--- a/internal/pipeline/scorecard.go
+++ b/internal/pipeline/scorecard.go
@@ -11,6 +11,7 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/mvanhorn/cli-printing-press/v3/internal/naming"
 	apispec "github.com/mvanhorn/cli-printing-press/v3/internal/spec"
 	"gopkg.in/yaml.v3"
 )
@@ -108,7 +109,11 @@ type CompScore struct {
 // RunScorecard evaluates generated CLI files and produces a scorecard.
 // If verifyReport is non-nil, verify results calibrate the final score.
 func RunScorecard(outputDir, pipelineDir, specPath string, verifyReport *VerifyReport) (*Scorecard, error) {
-	sc := &Scorecard{APIName: filepath.Base(outputDir)}
+	// Strip the CLI suffix because outputDir from fullrun (paths.WorkingCLIDir)
+	// and library checkouts both end in -pp-cli; APIName is the API slug,
+	// not the binary name, and lands in user-visible output (Markdown
+	// scorecard header, "Quality Scorecard:" CLI line).
+	sc := &Scorecard{APIName: naming.TrimCLISuffix(filepath.Base(outputDir))}
 
 	if err := scoreScorecardDimensions(sc, outputDir, specPath, verifyReport); err != nil {
 		return nil, err
diff --git a/internal/pipeline/scorecard_artifacts_test.go b/internal/pipeline/scorecard_artifacts_test.go
index 1384e6d4..f53d1ce9 100644
--- a/internal/pipeline/scorecard_artifacts_test.go
+++ b/internal/pipeline/scorecard_artifacts_test.go
@@ -34,3 +34,25 @@ func TestRunScorecardLoadsResearchFromSiblingResearchDir(t *testing.T) {
 	assert.Len(t, scorecard.CompetitorScores, 1)
 	assert.FileExists(t, filepath.Join(proofsDir, "scorecard.md"))
 }
+
+// TestRunScorecardStripsCLISuffixFromAPIName — APIName lands in the
+// Markdown scorecard header and the "Quality Scorecard:" CLI line.
+// fullrun passes paths.WorkingCLIDir (always -pp-cli suffixed), and
+// library checkouts share that shape; APIName must be the bare slug,
+// not the binary name.
+func TestRunScorecardStripsCLISuffixFromAPIName(t *testing.T) {
+	parent := t.TempDir()
+	suffixedDir := filepath.Join(parent, "producthunt-pp-cli")
+	require.NoError(t, os.MkdirAll(suffixedDir, 0o755))
+
+	sc, err := RunScorecard(suffixedDir, t.TempDir(), "", nil)
+	require.NoError(t, err)
+	assert.Equal(t, "producthunt", sc.APIName, "APIName must drop the -pp-cli binary suffix")
+
+	// Bare-slug dirs (local library convention) must pass through unchanged.
+	bareDir := filepath.Join(parent, "notion")
+	require.NoError(t, os.MkdirAll(bareDir, 0o755))
+	scBare, err := RunScorecard(bareDir, t.TempDir(), "", nil)
+	require.NoError(t, err)
+	assert.Equal(t, "notion", scBare.APIName, "bare-slug dirs must pass through unchanged")
+}

← 2899613d fix(cli): mcp-sync stops conflating API slug with binary nam  ·  back to Cli Printing Press  ·  fix(generator): three template defaults polish has to fix ma aab364be →